Beispiel #1
0
        static int GenericTypeBacktickSearch(IList <Node> childNodes, EcmaDesc desc)
        {
            /* Our strategy is to search for the non-generic variant of the type
             * (which in most case should fail) and then use the closest index
             * to linearily search for the generic variant with the right generic arg number
             */
            var searchNode = new Node()
            {
                Caption = desc.TypeName
            };
            int index = childNodes.BinarySearch(searchNode, EcmaTypeNodeComparer.Instance);

            // Place the index in the right start position
            if (index < 0)
            {
                index = ~index;
            }

            for (int i = index; i < childNodes.Count; i++)
            {
                var currentNode = childNodes[i];
                // Find the index of the generic argument list
                int genericIndex = currentNode.Caption.IndexOf('<');
                // If we are not on the same base type name anymore, there is no point
                int captionSlice = genericIndex != -1 ? genericIndex : currentNode.Caption.LastIndexOf(' ');
                if (string.Compare(searchNode.Caption, 0,
                                   currentNode.Caption, 0,
                                   Math.Max(captionSlice, searchNode.Caption.Length),
                                   StringComparison.Ordinal) != 0)
                {
                    break;
                }

                var numGenerics = CountTypeGenericArguments(currentNode.Caption, genericIndex);
                if (numGenerics == desc.GenericTypeArguments.Count)
                {
                    // Simple comparison if we are not looking for an inner type
                    if (desc.NestedType == null)
                    {
                        return(i);
                    }
                    // If more complicated, we fallback to using EcmaUrlParser
                    var caption = currentNode.Caption;
                    caption = "T:" + caption.Substring(0, caption.LastIndexOf(' ')).Replace('.', '+');
                    EcmaDesc otherDesc;
                    var      parser = new EcmaUrlParser();
                    if (parser.TryParse(caption, out otherDesc) && desc.NestedType.Equals(otherDesc.NestedType))
                    {
                        return(i);
                    }
                }
            }

            return(-1);
        }
Beispiel #2
0
		void RewriteCrefsIfNecessary (XDocument doc, string path)
		{
			// we also have to rewrite crefs
			var sees = doc.Descendants ().Where (d => d.Name.LocalName == "see").ToArray ();
			foreach (var see in sees) {
				var cref = see.Attribute ("cref");
				if (cref == null) {
					continue;
				}
				EcmaUrlParser parser = new EcmaUrlParser ();
				EcmaDesc reference;
				if (!parser.TryParse (cref.Value, out reference)) {
					continue;
				}
				if ((new EcmaDesc.Kind[] {
					EcmaDesc.Kind.Constructor,
					EcmaDesc.Kind.Method
				}).Any (k => k == reference.DescKind)) {
					string ns = reference.Namespace;
					string type = reference.TypeName;
					string memberName = reference.MemberName;
					if (reference.MemberArguments != null) {
						XDocument refDoc = FindReferenceDoc (path, doc, ns, type);
						if (refDoc == null) {
							continue;
						}
						// look in the refDoc for the memberName, and match on parameters and # of type parameters
						var overloads = refDoc.XPathSelectElements ("//Member[@MemberName='" + memberName + "']").ToArray ();
						// Do some initial filtering to find members that could potentially match (based on parameter and typeparam counts)
						var members = overloads.Where (e => reference.MemberArgumentsCount == e.XPathSelectElements ("Parameters/Parameter[not(@apistyle) or @apistyle='classic']").Count () && reference.GenericMemberArgumentsCount == e.XPathSelectElements ("TypeParameters/TypeParameter[not(@apistyle) or @apistyle='classic']").Count ()).Select (m => new {
							Node = m,
							AllParameters = m.XPathSelectElements ("Parameters/Parameter").ToArray (),
							Parameters = m.XPathSelectElements ("Parameters/Parameter[not(@apistyle) or @apistyle='classic']").ToArray (),
							NewParameters = m.XPathSelectElements ("Parameters/Parameter[@apistyle='unified']").ToArray ()
						}).ToArray ();
						// now find the member that matches on types
						var member = members.FirstOrDefault (m => reference.MemberArguments.All (r => m.Parameters.Any (mp => mp.Attribute ("Type").Value.Contains (r.TypeName))));
						if (member == null || member.NewParameters.Length == 0)
							continue;
						foreach (var arg in reference.MemberArguments) {
							// find the "classic" parameter
							var oldParam = member.Parameters.First (p => p.Attribute ("Type").Value.Contains (arg.TypeName));
							var newParam = member.NewParameters.FirstOrDefault (p => oldParam.Attribute ("Name").Value == p.Attribute ("Name").Value);
							if (newParam != null) {
								// this means there was a change made, and we should try to convert this cref
								arg.TypeName = NativeTypeManager.ConvertToNativeType (arg.TypeName);
							}
						}
						var rewrittenReference = reference.ToEcmaCref ();
						Console.WriteLine ("From {0} to {1}", cref.Value, rewrittenReference);
						cref.Value = rewrittenReference;
					}
				}
			}
		}
Beispiel #3
0
        void RewriteCrefsIfNecessary(XDocument doc, string path)
        {
            // we also have to rewrite crefs
            var sees = doc.Descendants().Where(d => d.Name.LocalName == "see").ToArray();

            foreach (var see in sees)
            {
                var cref = see.Attribute("cref");
                if (cref == null)
                {
                    continue;
                }
                EcmaUrlParser parser = new EcmaUrlParser();
                EcmaDesc      reference;
                if (!parser.TryParse(cref.Value, out reference))
                {
                    continue;
                }
                if ((new EcmaDesc.Kind[] {
                    EcmaDesc.Kind.Constructor,
                    EcmaDesc.Kind.Method
                }).Any(k => k == reference.DescKind))
                {
                    string ns         = reference.Namespace;
                    string type       = reference.TypeName;
                    string memberName = reference.MemberName;
                    if (reference.MemberArguments != null)
                    {
                        XDocument refDoc = FindReferenceDoc(path, doc, ns, type);
                        if (refDoc == null)
                        {
                            continue;
                        }
                        // look in the refDoc for the memberName, and match on parameters and # of type parameters
                        var overloads = refDoc.XPathSelectElements("//Member[@MemberName='" + memberName + "']").ToArray();
                        // Do some initial filtering to find members that could potentially match (based on parameter and typeparam counts)
                        var members = overloads.Where(e => reference.MemberArgumentsCount == e.XPathSelectElements("Parameters/Parameter[not(@apistyle) or @apistyle='classic']").Count() && reference.GenericMemberArgumentsCount == e.XPathSelectElements("TypeParameters/TypeParameter[not(@apistyle) or @apistyle='classic']").Count()).Select(m => new {
                            Node          = m,
                            AllParameters = m.XPathSelectElements("Parameters/Parameter").ToArray(),
                            Parameters    = m.XPathSelectElements("Parameters/Parameter[not(@apistyle) or @apistyle='classic']").ToArray(),
                            NewParameters = m.XPathSelectElements("Parameters/Parameter[@apistyle='unified']").ToArray()
                        }).ToArray();
                        // now find the member that matches on types
                        var member = members.FirstOrDefault(m => reference.MemberArguments.All(r => m.Parameters.Any(mp => mp.Attribute("Type").Value.Contains(r.TypeName))));
                        if (member == null || member.NewParameters.Length == 0)
                        {
                            continue;
                        }
                        foreach (var arg in reference.MemberArguments)
                        {
                            // find the "classic" parameter
                            var oldParam = member.Parameters.First(p => p.Attribute("Type").Value.Contains(arg.TypeName));
                            var newParam = member.NewParameters.FirstOrDefault(p => oldParam.Attribute("Name").Value == p.Attribute("Name").Value);
                            if (newParam != null)
                            {
                                // this means there was a change made, and we should try to convert this cref
                                arg.TypeName = NativeTypeManager.ConvertToNativeType(arg.TypeName);
                            }
                        }
                        var rewrittenReference = reference.ToEcmaCref();
                        Console.WriteLine("From {0} to {1}", cref.Value, rewrittenReference);
                        cref.Value = rewrittenReference;
                    }
                }
            }
        }
Beispiel #4
0
        public static Node MatchNodeWithEcmaUrl(string url, Tree tree)
        {
            Node     result = null;
            EcmaDesc desc;

            if (!parser.TryParse(url, out desc))
            {
                return(null);
            }

            // Namespace search
            Node currentNode = tree.RootNode;
            Node searchNode  = new Node()
            {
                Caption = desc.Namespace
            };
            int index = currentNode.ChildNodes.BinarySearch(searchNode, EcmaGenericNodeComparer.Instance);

            if (index >= 0)
            {
                result = currentNode.ChildNodes[index];
            }
            if (desc.DescKind == EcmaDesc.Kind.Namespace || index < 0)
            {
                return(result);
            }

            // Type search
            currentNode        = result;
            result             = null;
            searchNode.Caption = desc.ToCompleteTypeName();
            if (!desc.GenericTypeArgumentsIsNumeric)
            {
                index = currentNode.ChildNodes.BinarySearch(searchNode, EcmaTypeNodeComparer.Instance);
            }
            else
            {
                index = GenericTypeBacktickSearch(currentNode.ChildNodes, desc);
            }
            if (index >= 0)
            {
                result = currentNode.ChildNodes[index];
            }
            if ((desc.DescKind == EcmaDesc.Kind.Type && !desc.IsEtc) || index < 0)
            {
                return(result);
            }

            // Member selection
            currentNode = result;
            result      = null;
            var caption = desc.IsEtc ? EtcKindToCaption(desc.Etc) : MemberKindToCaption(desc.DescKind);

            currentNode = FindNodeForCaption(currentNode.ChildNodes, caption);
            if (currentNode == null ||
                (desc.IsEtc && desc.DescKind == EcmaDesc.Kind.Type && string.IsNullOrEmpty(desc.EtcFilter)))
            {
                return(currentNode);
            }

            // Member search
            result = null;
            var format = desc.DescKind == EcmaDesc.Kind.Constructor ? EcmaDesc.Format.WithArgs : EcmaDesc.Format.WithoutArgs;

            searchNode.Caption = desc.ToCompleteMemberName(format);
            index = currentNode.ChildNodes.BinarySearch(searchNode, EcmaGenericNodeComparer.Instance);
            if (index < 0)
            {
                return(null);
            }
            result = currentNode.ChildNodes[index];
            if (result.ChildNodes.Count == 0 || desc.IsEtc)
            {
                return(result);
            }

            // Overloads search
            currentNode        = result;
            searchNode.Caption = desc.ToCompleteMemberName(EcmaDesc.Format.WithArgs);
            index = currentNode.ChildNodes.BinarySearch(searchNode, EcmaGenericNodeComparer.Instance);
            if (index < 0)
            {
                return(result);
            }
            result = result.ChildNodes[index];

            return(result);
        }
Beispiel #5
0
        public Node InternalMatchNode(string url)
        {
            Node result = null;
            //Console.WriteLine ("Ecma-hs MatchNode with {0}", url);
            EcmaDesc desc;

            if (!parser.TryParse(url, out desc))
            {
                return(null);
            }

            //Console.WriteLine ("EcmaDesc: {0}", desc.ToString ());
            // Namespace search
            Node currentNode = Tree.RootNode;
            Node searchNode  = new Node()
            {
                Caption = desc.Namespace
            };
            int index = currentNode.Nodes.BinarySearch(searchNode, EcmaGenericNodeComparer.Instance);

            if (index >= 0)
            {
                result = currentNode.Nodes[index];
            }
            if (desc.DescKind == EcmaDesc.Kind.Namespace || index < 0)
            {
                return(result);
            }

            //Console.WriteLine ("Post NS");

            // Type search
            currentNode        = result;
            result             = null;
            searchNode.Caption = desc.ToCompleteTypeName();
            //Console.WriteLine ("Type search: {0}", searchNode.Caption);
            index = currentNode.Nodes.BinarySearch(searchNode, EcmaTypeNodeComparer.Instance);
            if (index >= 0)
            {
                result = currentNode.Nodes[index];
            }
            if ((desc.DescKind == EcmaDesc.Kind.Type && !desc.IsEtc) || index < 0)
            {
                return(result);
            }

            //Console.WriteLine ("Post Type");

            // Member selection
            currentNode = result;
            result      = null;
            var caption = desc.IsEtc ? EtcKindToCaption(desc.Etc) : MemberKindToCaption(desc.DescKind);

            currentNode = FindNodeForCaption(currentNode.Nodes, caption);
            if (currentNode == null ||
                (desc.IsEtc && desc.DescKind == EcmaDesc.Kind.Type && string.IsNullOrEmpty(desc.EtcFilter)))
            {
                return(currentNode);
            }

            //Console.WriteLine ("Post caption");

            // Member search
            result = null;
            var format = desc.DescKind == EcmaDesc.Kind.Constructor ? EcmaDesc.Format.WithArgs : EcmaDesc.Format.WithoutArgs;

            searchNode.Caption = desc.ToCompleteMemberName(format);
            //Console.WriteLine ("Member caption {0}", searchNode.Caption);
            index = currentNode.Nodes.BinarySearch(searchNode, EcmaGenericNodeComparer.Instance);
            if (index < 0)
            {
                //foreach (var n in currentNode.Nodes)
                //	Console.WriteLine (n.Caption);
                return(null);
            }
            result = currentNode.Nodes[index];
            //Console.WriteLine ("Member result: {0} {1} {2}", result.Caption, result.Nodes.Count, desc.IsEtc);
            if (result.Nodes.Count == 0 || desc.IsEtc)
            {
                return(result);
            }

            //Console.WriteLine ("Post member");

            // Overloads search
            currentNode        = result;
            searchNode.Caption = desc.ToCompleteMemberName(EcmaDesc.Format.WithArgs);
            //Console.WriteLine ("Overload caption: {0}", searchNode.Caption);
            //Console.WriteLine ("Candidates: {0}", string.Join (", ", currentNode.Nodes.Select (n => n.Caption)));
            index = currentNode.Nodes.BinarySearch(searchNode, EcmaGenericNodeComparer.Instance);
            if (index < 0)
            {
                return(result);
            }
            result = result.Nodes[index];

            return(result);
        }