Пример #1
0
        public void ArgumentContainsSingleResult()
        {
            var doc = new XPathDocument("468306.xml");

            var result =
                doc.Evaluate("string(/article[1]/front[1]/article-meta[1]/contrib-group[1]/contrib[1]/name[1]/surname[1])");

            Assert.IsTrue(result is string, "Type was: " + result.GetType().ToString());
        }
Пример #2
0
        // Methods
        public static int Main(string[] args)
        {
            XPathDocument document;

            ConsoleApplication.WriteBanner();

            OptionCollection options = new OptionCollection {
                new SwitchOption("?", "Show this help page."),
                new StringOption("config", "Specify a configuration file.", "versionCatalog"),
                new StringOption("out", "Specify an output file containing version information.", "outputFile"),
                new BooleanOption("rip", "Specify whether to rip old APIs which are not supported by the " +
                    "latest versions.")
            };

            ParseArgumentsResult result = options.ParseArguments(args);

            if(result.Options["?"].IsPresent)
            {
                Console.WriteLine("VersionBuilder [options]");
                options.WriteOptionSummary(Console.Out);
                return 0;
            }

            if(!result.Success)
            {
                result.WriteParseErrors(Console.Out);
                return 1;
            }

            if(result.UnusedArguments.Count != 0)
            {
                Console.WriteLine("No non-option arguments are supported.");
                return 1;
            }

            if(!result.Options["config"].IsPresent)
            {
                ConsoleApplication.WriteMessage(LogLevel.Error, "You must specify a version catalog file.");
                return 1;
            }

            bool rip = true;

            if(result.Options["rip"].IsPresent && !((bool)result.Options["rip"].Value))
                rip = false;

            string uri = (string)result.Options["config"].Value;

            try
            {
                document = new XPathDocument(uri);
            }
            catch(IOException ioEx)
            {
                ConsoleApplication.WriteMessage(LogLevel.Error, String.Format(CultureInfo.CurrentCulture,
                    "An error occurred while accessing the version catalog file '{0}'. The error message " +
                    "is: {1}", uri, ioEx.Message));
                return 1;
            }
            catch(XmlException xmlEx)
            {
                ConsoleApplication.WriteMessage(LogLevel.Error, String.Format(CultureInfo.CurrentCulture,
                    "The version catalog file '{0}' is not well-formed. The error message is: {1}", uri,
                    xmlEx.Message));
                return 1;
            }

            XPathNavigator navigator = document.CreateNavigator().SelectSingleNode("versions");
            XPathExpression expr = XPathExpression.Compile("string(ancestor::versions/@name)");
            List<VersionInfo> allVersions = new List<VersionInfo>();
            List<string> latestVersions = new List<string>();

            foreach(XPathNavigator navigator2 in document.CreateNavigator().Select("versions//version[@file]"))
            {
                string group = (string)navigator2.Evaluate(expr);
                string attribute = navigator2.GetAttribute("name", String.Empty);

                if(string.IsNullOrEmpty(attribute))
                    ConsoleApplication.WriteMessage(LogLevel.Error, "Every version element must have a name attribute.");

                string name = navigator2.GetAttribute("file", String.Empty);

                if(String.IsNullOrEmpty(attribute))
                    ConsoleApplication.WriteMessage(LogLevel.Error, "Every version element must have a file attribute.");

                string ripOldString = navigator2.GetAttribute("ripOldApis", String.Empty);
                bool ripOld = ripOldString == "1" || String.Equals("true", ripOldString, StringComparison.OrdinalIgnoreCase);

                name = Environment.ExpandEnvironmentVariables(name);
                VersionInfo item = new VersionInfo(attribute, group, name, ripOld);
                allVersions.Add(item);
            }

            string str5 = String.Empty;

            foreach(VersionInfo info2 in allVersions)
                if(!info2.RipOldApis && (!rip || info2.Group != str5))
                {
                    latestVersions.Add(info2.Name);
                    str5 = info2.Group;
                }

            bool ripAny = rip || allVersions.Any(i => i.RipOldApis);

            if(Cancel)
            {
                ConsoleApplication.WriteMessage(LogLevel.Info, "VersionBuilder canceled");
                return 1;
            }

            XmlReaderSettings settings = new XmlReaderSettings
            {
                IgnoreWhitespace = true
            };

            XmlWriterSettings settings2 = new XmlWriterSettings
            {
                Indent = true
            };

            Dictionary<string, List<KeyValuePair<string, string>>> versionIndex = new Dictionary<string, List<KeyValuePair<string, string>>>();
            Dictionary<string, Dictionary<string, ElementInfo>> dictionary2 = new Dictionary<string, Dictionary<string, ElementInfo>>();
            Dictionary<string, Dictionary<String, XPathNavigator>> extensionMethods = new Dictionary<string, Dictionary<String, XPathNavigator>>();
            XPathExpression expression2 = XPathExpression.Compile("string(/api/@id)");
            XPathExpression expression4 = XPathExpression.Compile("/api/elements/element");
            XPathExpression expression = XPathExpression.Compile("/api/attributes/attribute[type[@api='T:System.ObsoleteAttribute']]");
            XPathExpression extensionAttributeExpression = XPathExpression.Compile("/api/attributes/attribute[type[@api='T:System.Runtime.CompilerServices.ExtensionAttribute']]");
            XPathExpression extensionFirstParameterExpression = XPathExpression.Compile("/api/parameters/parameter[1]/*");
            XPathExpression specialization = XPathExpression.Compile("./specialization");
            XPathExpression templates = XPathExpression.Compile("./template[boolean(@index) and starts-with(@api, 'M:')]");
            XPathExpression skipFirstParam = XPathExpression.Compile("./parameter[position()>1]" );
            XPathExpression expression6 = XPathExpression.Compile("boolean(argument[type[@api='T:System.Boolean'] and value[.='True']])");
            XPathExpression apiChild = XPathExpression.Compile("./api");

            foreach(VersionInfo info3 in allVersions)
            {
                if(Cancel)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Info, "VersionBuilder canceled");
                    return 1;
                }

                ConsoleApplication.WriteMessage(LogLevel.Info, String.Format(CultureInfo.CurrentCulture,
                    "Indexing version '{0}' using file '{1}'.", info3.Name, info3.File));
                try
                {
                    XmlReader reader = XmlReader.Create(info3.File, settings);
                    try
                    {
                        reader.MoveToContent();
                        while(reader.Read())
                        {
                            if((reader.NodeType == XmlNodeType.Element) && (reader.LocalName == "api"))
                            {
                                string key = String.Empty;
                                List<KeyValuePair<string, string>> list3 = null;
                                string str7 = String.Empty;
                                Dictionary<string, ElementInfo> dictionary3 = null;
                                XmlReader reader2 = reader.ReadSubtree();
                                XPathNavigator navigator3 = new XPathDocument(reader2).CreateNavigator();

                                key = (string)navigator3.Evaluate(expression2);

                                if(!versionIndex.TryGetValue(key, out list3))
                                {
                                    list3 = new List<KeyValuePair<string, string>>();
                                    versionIndex.Add(key, list3);
                                }

                                if(!dictionary2.TryGetValue(key, out dictionary3))
                                {
                                    dictionary3 = new Dictionary<string, ElementInfo>();
                                    dictionary2.Add(key, dictionary3);
                                }

                                foreach(XPathNavigator navigator4 in navigator3.Select(expression4))
                                {
                                    ElementInfo info4;
                                    string str8 = navigator4.GetAttribute("api", String.Empty);
                                    if(!dictionary3.TryGetValue(str8, out info4))
                                    {
                                        XPathNavigator elementNode = null;
                                        if((navigator4.SelectSingleNode("*") != null) || (navigator4.SelectChildren(XPathNodeType.Attribute).Count > 1))
                                        {
                                            elementNode = navigator4;
                                        }
                                        info4 = new ElementInfo(info3.Group, info3.Name, elementNode);
                                        dictionary3.Add(str8, info4);
                                        continue;
                                    }
                                    if(!info4.Versions.ContainsKey(info3.Group))
                                    {
                                        info4.Versions.Add(info3.Group, info3.Name);
                                    }
                                }
                                XPathNavigator navigator6 = navigator3.SelectSingleNode(expression);
                                if(navigator6 != null)
                                {
                                    str7 = ((bool)navigator6.Evaluate(expression6)) ? "error" : "warning";
                                }

                                if(key.StartsWith("M:", StringComparison.Ordinal))
                                {
                                    // Only check for extension methods when this is actually a method in question
                                    var navigator7 = navigator3.SelectSingleNode(extensionAttributeExpression);
                                    if(navigator7 != null)
                                    {
                                        // Check first parameter
                                        var navigator8 = navigator3.SelectSingleNode(extensionFirstParameterExpression);
                                        if(navigator8 != null)
                                        {
                                            // Get type node
                                            var typeID = navigator8.GetAttribute("api", String.Empty);
                                            if(navigator8.LocalName == "type")
                                            {
                                                var specNode = navigator8.SelectSingleNode(specialization);
                                                if(specNode == null || specNode.SelectChildren(XPathNodeType.Element).Count == specNode.Select(templates).Count)
                                                {
                                                    // Either non-generic type or all type parameters are from within this method
                                                    Dictionary<String, XPathNavigator> extMethods;
                                                    if(!extensionMethods.TryGetValue(typeID, out extMethods))
                                                    {
                                                        extMethods = new Dictionary<String, XPathNavigator>();
                                                        extensionMethods.Add(typeID, extMethods);
                                                    }
                                                    if(!extMethods.ContainsKey(key))
                                                    {
                                                        extMethods.Add(key, navigator3.SelectSingleNode(apiChild));
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                // TODO extension methods for generic parameters...
                                            }
                                        }
                                    }
                                }

                                list3.Add(new KeyValuePair<string, string>(info3.Name, str7));
                                str7 = String.Empty;
                                reader2.Close();
                            }
                        }
                    }
                    finally
                    {
                        reader.Close();
                    }
                    continue;
                }
                catch(IOException ioEx)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format(CultureInfo.CurrentCulture,
                        "An error occurred while accessing the input file '{0}'. The error message is: {1}",
                        info3.File, ioEx.Message));
                    return 1;
                }
                catch(XmlException xmlEx)
                {
                    ConsoleApplication.WriteMessage(LogLevel.Error, String.Format(CultureInfo.CurrentCulture,
                        "The input file '{0}' is not well-formed. The error message is: {1}", info3.File,
                        xmlEx.Message));
                    return 1;
                }
            }

            if(ripAny)
                RemoveOldApis(versionIndex, latestVersions);

            ConsoleApplication.WriteMessage(LogLevel.Info, String.Format(CultureInfo.CurrentCulture,
                "Indexed {0} entities in {1} versions.", versionIndex.Count, allVersions.Count));

            try
            {
                XmlWriter writer;

                if(result.Options["out"].IsPresent)
                    writer = XmlWriter.Create((string)result.Options["out"].Value, settings2);
                else
                    writer = XmlWriter.Create(Console.Out, settings2);

                try
                {
                    writer.WriteStartDocument();
                    writer.WriteStartElement("reflection");
                    writer.WriteStartElement("assemblies");
                    Dictionary<string, object> dictionary4 = new Dictionary<string, object>();

                    foreach(VersionInfo info5 in allVersions)
                    {
                        if(Cancel)
                        {
                            ConsoleApplication.WriteMessage(LogLevel.Info, "VersionBuilder canceled");
                            return 1;
                        }

                        using(XmlReader reader3 = XmlReader.Create(info5.File, settings))
                        {
                            reader3.MoveToContent();

                            while(reader3.Read())
                            {
                                if((reader3.NodeType == XmlNodeType.Element) && (reader3.LocalName == "assembly"))
                                {
                                    string str9 = reader3.GetAttribute("name");
                                    if(!dictionary4.ContainsKey(str9))
                                    {
                                        XmlReader reader4 = reader3.ReadSubtree();
                                        writer.WriteNode(reader4, false);
                                        reader4.Close();
                                        dictionary4.Add(str9, null);
                                    }
                                }
                            }
                        }
                    }

                    writer.WriteEndElement();
                    writer.WriteStartElement("apis");
                    var readElements = new HashSet<String>();

                    foreach(VersionInfo info6 in allVersions)
                    {
                        if(Cancel)
                        {
                            ConsoleApplication.WriteMessage(LogLevel.Info, "VersionBuilder canceled");
                            return 1;
                        }

                        XmlReader reader5 = XmlReader.Create(info6.File, settings);
                        reader5.MoveToContent();

                        while(reader5.Read())
                        {
                            if((reader5.NodeType == XmlNodeType.Element) && (reader5.LocalName == "api"))
                            {
                                string str10 = reader5.GetAttribute("id");
                                if(versionIndex.ContainsKey(str10))
                                {
                                    List<KeyValuePair<string, string>> versions = versionIndex[str10];
                                    KeyValuePair<string, string> pair = versions[0];
                                    if(info6.Name == pair.Key)
                                    {
                                        writer.WriteStartElement("api");
                                        writer.WriteAttributeString("id", str10);
                                        XmlReader reader6 = reader5.ReadSubtree();
                                        reader6.MoveToContent();
                                        reader6.ReadStartElement();
                                        Dictionary<String, XPathNavigator> eElems;
                                        var hasExtensionMethods = extensionMethods.TryGetValue(str10, out eElems);
                                        if(hasExtensionMethods)
                                        {
                                            readElements.Clear();
                                            readElements.UnionWith(extensionMethods[str10].Keys);
                                        }
                                        while(!reader6.EOF)
                                        {
                                            if((reader6.NodeType == XmlNodeType.Element) && (reader6.LocalName == "elements"))
                                            {
                                                Dictionary<string, ElementInfo> dictionary5 = dictionary2[str10];
                                                Dictionary<string, object> dictionary6 = new Dictionary<string, object>();
                                                writer.WriteStartElement("elements");
                                                XmlReader reader7 = reader6.ReadSubtree();
                                                foreach(XPathNavigator navigator8 in new XPathDocument(reader7).CreateNavigator().Select("elements/element"))
                                                {
                                                    string str11 = navigator8.GetAttribute("api", String.Empty);
                                                    dictionary6[str11] = null;
                                                    writer.WriteStartElement("element");
                                                    writer.WriteAttributeString("api", str11);
                                                    if(hasExtensionMethods)
                                                    {
                                                        readElements.Remove(str11);
                                                    }
                                                    foreach(string str12 in dictionary5[str11].Versions.Keys)
                                                    {
                                                        writer.WriteAttributeString(str12, dictionary5[str11].Versions[str12]);
                                                    }
                                                    foreach(XPathNavigator navigator9 in navigator8.Select("@*"))
                                                    {
                                                        if(navigator9.LocalName != "api")
                                                        {
                                                            writer.WriteAttributeString(navigator9.LocalName, navigator9.Value);
                                                        }
                                                    }
                                                    foreach(XPathNavigator navigator10 in navigator8.Select("*"))
                                                    {
                                                        writer.WriteNode(navigator10, false);
                                                    }
                                                    writer.WriteEndElement();
                                                }
                                                reader7.Close();
                                                if(dictionary6.Count != dictionary5.Count)
                                                {
                                                    foreach(string str13 in dictionary5.Keys)
                                                    {
                                                        if(dictionary6.ContainsKey(str13) || (ripAny && !IsLatestElement(dictionary5[str13].Versions.Values, latestVersions)))
                                                        {
                                                            continue;
                                                        }
                                                        writer.WriteStartElement("element");
                                                        writer.WriteAttributeString("api", str13);
                                                        if(hasExtensionMethods)
                                                        {
                                                            readElements.Remove(str13);
                                                        }
                                                        foreach(string str14 in dictionary5[str13].Versions.Keys)
                                                        {
                                                            writer.WriteAttributeString(str14, dictionary5[str13].Versions[str14]);
                                                        }
                                                        if(dictionary5[str13].ElementNode != null)
                                                        {
                                                            foreach(XPathNavigator navigator11 in dictionary5[str13].ElementNode.Select("@*"))
                                                            {
                                                                if(navigator11.LocalName != "api")
                                                                {
                                                                    writer.WriteAttributeString(navigator11.LocalName, navigator11.Value);
                                                                }
                                                            }
                                                            foreach(XPathNavigator navigator12 in dictionary5[str13].ElementNode.Select("*"))
                                                            {
                                                                writer.WriteNode(navigator12, false);
                                                            }
                                                        }
                                                        writer.WriteEndElement();
                                                    }
                                                }

                                                if(hasExtensionMethods)
                                                {
                                                    foreach(var eMethodID in readElements)
                                                    {
                                                        writer.WriteStartElement("element");
                                                        writer.WriteAttributeString("api", eMethodID);
                                                        writer.WriteAttributeString("source", "extension");
                                                        foreach(XPathNavigator extMember in eElems[eMethodID].SelectChildren(XPathNodeType.Element))
                                                        {
                                                            switch(extMember.LocalName)
                                                            {
                                                                case "apidata":
                                                                    writer.WriteStartElement("apidata");
                                                                    foreach(XPathNavigator apidataAttr in extMember.Select("@*"))
                                                                    {
                                                                        writer.WriteAttributeString(apidataAttr.LocalName, apidataAttr.Value);
                                                                    }
                                                                    writer.WriteAttributeString("subsubgroup", "extension");
                                                                    foreach(XPathNavigator child in extMember.SelectChildren(XPathNodeType.All & ~XPathNodeType.Attribute))
                                                                    {
                                                                        writer.WriteNode(child, false);
                                                                    }
                                                                    writer.WriteEndElement();
                                                                    break;
                                                                case "parameters":
                                                                    var noParamsWritten = true;
                                                                    foreach(XPathNavigator eParam in extMember.Select(skipFirstParam))
                                                                    {
                                                                        if(noParamsWritten)
                                                                        {
                                                                            writer.WriteStartElement("parameters");
                                                                            noParamsWritten = false;
                                                                        }
                                                                        writer.WriteNode(eParam, false);
                                                                    }
                                                                    if(!noParamsWritten)
                                                                    {
                                                                        writer.WriteEndElement();
                                                                    }
                                                                    break;
                                                                case "memberdata":
                                                                    writer.WriteStartElement("memberdata");
                                                                    foreach(XPathNavigator mDataAttr in extMember.Select("@*"))
                                                                    {
                                                                        if(mDataAttr.LocalName != "static")
                                                                        {
                                                                            writer.WriteAttributeString(mDataAttr.LocalName, mDataAttr.Value);
                                                                        }
                                                                    }
                                                                    foreach(XPathNavigator child in extMember.SelectChildren(XPathNodeType.All & ~XPathNodeType.Attribute))
                                                                    {
                                                                        writer.WriteNode(child, false);
                                                                    }
                                                                    writer.WriteEndElement();
                                                                    break;
                                                                case "attributes":
                                                                    break;
                                                                default:
                                                                    writer.WriteNode(extMember, false);
                                                                    break;
                                                            }
                                                        }
                                                        writer.WriteEndElement();
                                                    }
                                                }

                                                writer.WriteEndElement();
                                                reader6.Read();
                                            }
                                            else if(reader6.NodeType == XmlNodeType.Element)
                                            {
                                                writer.WriteNode(reader6, false);
                                            }
                                            else
                                            {
                                                reader6.Read();
                                            }
                                        }
                                        reader6.Close();
                                        writer.WriteStartElement("versions");
                                        foreach(XPathNavigator navigator13 in navigator.SelectChildren(XPathNodeType.Element))
                                        {
                                            WriteVersionTree(versions, navigator13, writer);
                                        }
                                        writer.WriteEndElement();
                                        writer.WriteEndElement();
                                    }
                                }
                            }
                        }

                        reader5.Close();
                    }

                    writer.WriteEndElement();
                    writer.WriteEndElement();
                    writer.WriteEndDocument();
                }
                finally
                {
                    writer.Close();
                }
            }
            catch(IOException ioEx)
            {
                ConsoleApplication.WriteMessage(LogLevel.Error, "An error occurred while generating the " +
                    "output file. The error message is: {0}", ioEx.Message);
                return 1;
            }

            return 0;
        }