Пример #1
0
        public static void PopulateTreeFromIndexFile(string indexFilePath,
                                                     string idPrefix,
                                                     Tree tree,
                                                     IDocStorage storage,
                                                     Dictionary <string, XElement> nsSummaries,
                                                     Func <XElement, string> indexGenerator = null)
        {
            var root  = tree.RootNode;
            int resID = 0;
            var asm   = Path.GetDirectoryName(indexFilePath);

            storage = storage ?? new Storage.NullStorage();
            // nsSummaries is allowed to be null if the user doesn't care about it
            nsSummaries = nsSummaries ?? new Dictionary <string, XElement> ();
            // default index generator uses a counter
            indexGenerator = indexGenerator ?? (_ => resID++.ToString());

            using (var reader = XmlReader.Create(File.OpenRead(indexFilePath))) {
                reader.ReadToFollowing("Types");
                var types = XElement.Load(reader.ReadSubtree());

                foreach (var ns in types.Elements("Namespace"))
                {
                    var nsName = (string)ns.Attribute("Name");
                    nsName = !string.IsNullOrEmpty(nsName) ? nsName : "global";
                    var nsNode = root.GetOrCreateNode(nsName, "N:" + nsName);

                    XElement nsElements;
                    if (!nsSummaries.TryGetValue(nsName, out nsElements))
                    {
                        nsSummaries[nsName] = nsElements = new XElement("elements",
                                                                        new XElement("summary"),
                                                                        new XElement("remarks"));
                    }

                    foreach (var type in ns.Elements("Type"))
                    {
                        // Add the XML file corresponding to the type to our storage
                        var    id = indexGenerator(type);
                        string typeFilePath;
                        var    typeDocument = EcmaDoc.LoadTypeDocument(asm, nsName, type.Attribute("Name").Value, out typeFilePath);
                        if (typeDocument == null)
                        {
                            continue;
                        }
                        using (var file = File.OpenRead(typeFilePath))
                            storage.Store(id, file);
                        nsElements.Add(ExtractClassSummary(typeFilePath));

                        var typeCaption = EcmaDoc.GetTypeCaptionFromIndex(type);
                        var url         = idPrefix + id + '#' + typeCaption + '/';
                        typeCaption = EcmaDoc.GetTypeCaptionFromIndex(type, true);
                        var typeNode = nsNode.CreateNode(typeCaption, url);

                        // Add meta "Members" node
                        typeNode.CreateNode("Members", "*");
                        var membersNode = typeDocument.Root.Element("Members");
                        if (membersNode == null || !membersNode.Elements().Any())
                        {
                            continue;
                        }
                        var members = membersNode
                                      .Elements("Member")
                                      .ToLookup(EcmaDoc.GetMemberType);

                        foreach (var memberType in members)
                        {
                            // We pluralize the member type to get the caption and take the first letter as URL
                            var node        = typeNode.CreateNode(EcmaDoc.PluralizeMemberType(memberType.Key), memberType.Key[0].ToString());
                            var memberIndex = 0;

                            var isCtors = memberType.Key[0] == 'C';

                            // We do not escape much member name here
                            foreach (var memberGroup in memberType.GroupBy(m => MakeMemberCaption(m, isCtors)))
                            {
                                if (memberGroup.Count() > 1)
                                {
                                    // Generate overload
                                    var overloadCaption = MakeMemberCaption(memberGroup.First(), false);
                                    var overloadNode    = node.CreateNode(overloadCaption, overloadCaption);
                                    foreach (var member in memberGroup)
                                    {
                                        overloadNode.CreateNode(MakeMemberCaption(member, true), (memberIndex++).ToString());
                                    }
                                    overloadNode.Sort();
                                }
                                else
                                {
                                    // We treat constructor differently by showing their argument list in all cases
                                    node.CreateNode(MakeMemberCaption(memberGroup.First(), isCtors), (memberIndex++).ToString());
                                }
                            }
                            node.Sort();
                        }
                    }

                    nsNode.Sort();
                }
                root.Sort();
            }
        }
Пример #2
0
        public static void PopulateTreeFromIndexFile(string indexFilePath,
                                                     string idPrefix,
                                                     Tree tree,
                                                     IDocStorage storage,
                                                     Dictionary <string, XElement> nsSummaries,
                                                     Func <XElement, string> indexGenerator = null,
                                                     IEcmaProviderFileSource fileSource     = null)
        {
            fileSource = fileSource ?? DefaultEcmaProviderFileSource.Default;
            var root  = tree.RootNode;
            int resID = 0;
            var asm   = Path.GetDirectoryName(indexFilePath);

            storage = storage ?? new Storage.NullStorage();
            // nsSummaries is allowed to be null if the user doesn't care about it
            nsSummaries = nsSummaries ?? new Dictionary <string, XElement> ();
            // default index generator uses a counter
            indexGenerator = indexGenerator ?? (_ => resID++.ToString());

            using (var reader = fileSource.GetIndexReader(indexFilePath)) {
                reader.ReadToFollowing("Types");
                var types = XElement.Load(reader.ReadSubtree());

                foreach (var ns in types.Elements("Namespace"))
                {
                    var nsName = (string)ns.Attribute("Name");
                    nsName = !string.IsNullOrEmpty(nsName) ? nsName : "global";
                    var nsNode = root.GetOrCreateNode(nsName, "N:" + nsName);

                    XElement nsElements;
                    if (!nsSummaries.TryGetValue(nsName, out nsElements))
                    {
                        nsSummaries[nsName] = nsElements = new XElement("elements",
                                                                        new XElement("summary"),
                                                                        new XElement("remarks"));
                    }
                    //Add namespace summary and remarks data from file, if available
                    var nsFileName = fileSource.GetNamespaceXmlPath(asm, nsName);

                    if (File.Exists(nsFileName))
                    {
                        var nsEl = fileSource.GetNamespaceElement(nsFileName);

                        nsElements.Element("summary").ReplaceWith(nsEl.Descendants("summary").First());
                        nsElements.Element("remarks").ReplaceWith(nsEl.Descendants("remarks").First());
                    }
                    else
                    {
                        Console.WriteLine("Error reading namespace XML for {0} at {1}", nsName, nsFileName);
                    }

                    foreach (var type in ns.Elements("Type"))
                    {
                        // Add the XML file corresponding to the type to our storage
                        var    id = indexGenerator(type);
                        string typeFilePath;
                        var    typeDocument = EcmaDoc.LoadTypeDocument(asm, nsName, type.Attribute("Name").Value, out typeFilePath, fileSource);
                        if (typeDocument == null)
                        {
                            continue;
                        }

                        // write the document (which may have been modified by the fileSource) to the storage
                        MemoryStream io = new MemoryStream();
                        using (var writer = XmlWriter.Create(io)) {
                            typeDocument.WriteTo(writer);
                        }
                        io.Seek(0, SeekOrigin.Begin);
                        storage.Store(id, io);

                        nsElements.Add(ExtractClassSummary(typeDocument));

                        var typeCaption = EcmaDoc.GetTypeCaptionFromIndex(type);
                        var url         = idPrefix + id + '#' + typeCaption + '/';
                        typeCaption = EcmaDoc.GetTypeCaptionFromIndex(type, true);
                        var typeNode = nsNode.CreateNode(typeCaption, url);

                        // Add meta "Members" node
                        typeNode.CreateNode("Members", "*");
                        var membersNode = typeDocument.Root.Element("Members");
                        if (membersNode == null || !membersNode.Elements().Any())
                        {
                            continue;
                        }
                        var members = membersNode
                                      .Elements("Member")
                                      .ToLookup(EcmaDoc.GetMemberType);

                        foreach (var memberType in members)
                        {
                            // We pluralize the member type to get the caption and take the first letter as URL
                            var node        = typeNode.CreateNode(EcmaDoc.PluralizeMemberType(memberType.Key), memberType.Key[0].ToString());
                            var memberIndex = 0;

                            var isCtors = memberType.Key[0] == 'C';

                            // We do not escape much member name here
                            foreach (var memberGroup in memberType.GroupBy(m => MakeMemberCaption(m, isCtors)))
                            {
                                if (memberGroup.Count() > 1)
                                {
                                    // Generate overload
                                    var overloadCaption = MakeMemberCaption(memberGroup.First(), false);
                                    var overloadNode    = node.CreateNode(overloadCaption, overloadCaption);
                                    foreach (var member in memberGroup)
                                    {
                                        overloadNode.CreateNode(MakeMemberCaption(member, true), (memberIndex++).ToString());
                                    }
                                    overloadNode.Sort();
                                }
                                else
                                {
                                    // We treat constructor differently by showing their argument list in all cases
                                    node.CreateNode(MakeMemberCaption(memberGroup.First(), isCtors), (memberIndex++).ToString());
                                }
                            }
                            node.Sort();
                        }
                    }

                    nsNode.Sort();
                }
                root.Sort();
            }
        }
Пример #3
0
        public override void PopulateSearchableIndex(IndexWriter writer)
        {
            StringBuilder      text      = new StringBuilder();
            SearchableDocument searchDoc = new SearchableDocument();

            foreach (Node ns_node in Tree.RootNode.ChildNodes)
            {
                foreach (Node type_node in ns_node.ChildNodes)
                {
                    string typename = type_node.Caption.Substring(0, type_node.Caption.IndexOf(' '));
                    string full = ns_node.Caption + "." + typename;
                    string url = type_node.PublicUrl;
                    string doc_tag = GetKindFromCaption(type_node.Caption);
                    string rest, hash;
                    var    id   = GetInternalIdForInternalUrl(type_node.GetInternalUrl(), out hash);
                    var    xdoc = XDocument.Load(GetHelpStream(id));
                    if (xdoc == null)
                    {
                        continue;
                    }
                    if (string.IsNullOrEmpty(doc_tag))
                    {
                        continue;
                    }

                    // For classes, structures or interfaces add a doc for the overview and
                    // add a doc for every constructor, method, event, ...
                    // doc_tag == "Class" || doc_tag == "Structure" || doc_tag == "Interface"
                    if (doc_tag[0] == 'C' || doc_tag[0] == 'S' || doc_tag[0] == 'I')
                    {
                        // Adds a doc for every overview of every type
                        SearchableDocument doc = searchDoc.Reset();
                        doc.Title     = type_node.Caption;
                        doc.HotText   = typename;
                        doc.Url       = url;
                        doc.FullTitle = full;

                        var node_sel = xdoc.Root.Element("Docs");
                        text.Clear();
                        GetTextFromNode(node_sel, text);
                        doc.Text = text.ToString();

                        text.Clear();
                        GetExamples(node_sel, text);
                        doc.Examples = text.ToString();

                        writer.AddDocument(doc.LuceneDoc);
                        var exportParsable = doc_tag[0] == 'C' && (ns_node.Caption.StartsWith("MonoTouch") || ns_node.Caption.StartsWith("MonoMac"));

                        //Add docs for contructors, methods, etc.
                        foreach (Node c in type_node.ChildNodes)                           // c = Constructors || Fields || Events || Properties || Methods || Operators
                        {
                            if (c.Element == "*")
                            {
                                continue;
                            }
                            const float innerTypeBoost = 0.2f;

                            IEnumerable <Node> ncnodes = c.ChildNodes;
                            // The rationale is that we need to properly handle method overloads
                            // so for those method node which have children, flatten them
                            if (c.Caption == "Methods")
                            {
                                ncnodes = ncnodes
                                          .Where(n => n.ChildNodes == null || n.ChildNodes.Count == 0)
                                          .Concat(ncnodes.Where(n => n.ChildNodes.Count > 0).SelectMany(n => n.ChildNodes));
                            }
                            else if (c.Caption == "Operators")
                            {
                                ncnodes = ncnodes
                                          .Where(n => !n.Caption.EndsWith("Conversion"))
                                          .Concat(ncnodes.Where(n => n.Caption.EndsWith("Conversion")).SelectMany(n => n.ChildNodes));
                            }

                            var prematchedMembers = xdoc.Root.Element("Members").Elements("Member").ToLookup(n => (string)n.Attribute("MemberName"), n => n);

                            foreach (Node nc in ncnodes)
                            {
                                XElement docsNode = null;
                                try {
                                    docsNode = GetDocsFromCaption(xdoc, c.Caption[0] == 'C' ? ".ctor" : nc.Caption, c.Caption[0] == 'O', prematchedMembers);
                                } catch {}
                                if (docsNode == null)
                                {
                                    Console.Error.WriteLine("Problem: {0}", nc.PublicUrl);
                                    continue;
                                }

                                SearchableDocument doc_nod = searchDoc.Reset();
                                doc_nod.Title     = LargeName(nc) + " " + EcmaDoc.EtcKindToCaption(c.Caption[0]);
                                doc_nod.FullTitle = ns_node.Caption + '.' + typename + "::" + nc.Caption;
                                doc_nod.HotText   = string.Empty;

                                /* Disable constructors hottext indexing as it's often "polluting" search queries
                                 * because it has the same hottext than standard types */
                                if (c.Caption != "Constructors")
                                {
                                    //dont add the parameters to the hottext
                                    int ppos = nc.Caption.IndexOf('(');
                                    doc_nod.HotText = ppos != -1 ? nc.Caption.Substring(0, ppos) : nc.Caption;
                                }

                                var urlnc = nc.PublicUrl;
                                doc_nod.Url = urlnc;

                                text.Clear();
                                GetTextFromNode(docsNode, text);
                                doc_nod.Text = text.ToString();

                                text.Clear();
                                GetExamples(docsNode, text);
                                doc_nod.Examples = text.ToString();

                                Document lucene_doc = doc_nod.LuceneDoc;
                                lucene_doc.Boost = innerTypeBoost;
                                writer.AddDocument(lucene_doc);

                                // Objective-C binding specific parsing of [Export] attributes
                                if (exportParsable)
                                {
                                    try {
                                        var exports = docsNode.Parent.Elements("Attributes").Elements("Attribute").Elements("AttributeName")
                                                      .Select(a => (string)a).Where(txt => txt.Contains("Foundation.Export"));

                                        foreach (var exportNode in exports)
                                        {
                                            var parts = exportNode.Split('"');
                                            if (parts.Length != 3)
                                            {
                                                Console.WriteLine("Export attribute not found or not usable in {0}", exportNode);
                                                continue;
                                            }

                                            var export      = parts[1];
                                            var export_node = searchDoc.Reset();
                                            export_node.Title     = export + " Export";
                                            export_node.FullTitle = ns_node.Caption + '.' + typename + "::" + export;
                                            export_node.Url       = urlnc;
                                            export_node.HotText   = export;
                                            export_node.Text      = string.Empty;
                                            export_node.Examples  = string.Empty;
                                            lucene_doc            = export_node.LuceneDoc;
                                            lucene_doc.Boost      = innerTypeBoost;
                                            writer.AddDocument(lucene_doc);
                                        }
                                    } catch (Exception e) {
                                        Console.WriteLine("Problem processing {0} for MonoTouch/MonoMac exports\n\n{0}", e);
                                    }
                                }
                            }
                        }
                        // doc_tag == "Enumeration"
                    }
                    else if (doc_tag[0] == 'E')
                    {
                        var members = xdoc.Root.Element("Members").Elements("Member");
                        if (members == null)
                        {
                            continue;
                        }

                        text.Clear();
                        foreach (var member_node in members)
                        {
                            string enum_value = (string)member_node.Attribute("MemberName");
                            text.Append(enum_value);
                            text.Append(" ");
                            GetTextFromNode(member_node.Element("Docs"), text);
                            text.AppendLine();
                        }

                        SearchableDocument doc = searchDoc.Reset();

                        text.Clear();
                        GetExamples(xdoc.Root.Element("Docs"), text);
                        doc.Examples = text.ToString();

                        doc.Title     = type_node.Caption;
                        doc.HotText   = (string)xdoc.Root.Attribute("Name");
                        doc.FullTitle = full;
                        doc.Url       = url;
                        doc.Text      = text.ToString();
                        writer.AddDocument(doc.LuceneDoc);
                        // doc_tag == "Delegate"
                    }
                    else if (doc_tag[0] == 'D')
                    {
                        SearchableDocument doc = searchDoc.Reset();
                        doc.Title     = type_node.Caption;
                        doc.HotText   = (string)xdoc.Root.Attribute("Name");
                        doc.FullTitle = full;
                        doc.Url       = url;

                        var node_sel = xdoc.Root.Element("Docs");

                        text.Clear();
                        GetTextFromNode(node_sel, text);
                        doc.Text = text.ToString();

                        text.Clear();
                        GetExamples(node_sel, text);
                        doc.Examples = text.ToString();

                        writer.AddDocument(doc.LuceneDoc);
                    }
                }
            }
        }