Пример #1
0
 void UpdateExistingLibraries(XDocument docs, HashSet <string> seenLibraries)
 {
     foreach (XElement types in docs.Root.Elements("Types"))
     {
         XAttribute       library = types.Attribute("Library");
         HashSet <string> libraryTypes;
         if (library == null || !libraries.TryGetValue(library.Value, out libraryTypes))
         {
             continue;
         }
         seenLibraries.Add(library.Value);
         var seenTypes = new HashSet <string> ();
         foreach (XElement type in types.Elements("Type").ToList())
         {
             XAttribute fullName = type.Attribute("FullName");
             string     typeName = fullName == null
                           ? null
                           : XmlDocUtils.ToEscapedTypeName(fullName.Value);
             if (typeName == null || !libraryTypes.Contains(typeName))
             {
                 continue;
             }
             type.Remove();
             seenTypes.Add(typeName);
             types.Add(LoadType(typeName, library.Value));
         }
         foreach (string typeName in libraryTypes.Except(seenTypes))
         {
             types.Add(LoadType(typeName, library.Value));
         }
     }
 }
Пример #2
0
        void ProcessFiles(Options opts, string format, List <string> files)
        {
            foreach (var basePath in
                     files.Select(f =>
                                  Path.Combine(Path.GetDirectoryName(f), Path.GetFileNameWithoutExtension(f)))
                     .Distinct())
            {
                string treeFile = basePath + ".tree";
                string zipFile  = basePath + ".zip";
                if (!Exists(treeFile) || !Exists(zipFile))
                {
                    continue;
                }
                string outDir = opts.OutputDirectory != null
                                        ? Path.Combine(opts.OutputDirectory, Path.GetFileName(basePath))
                                        : XmlDocUtils.GetCacheDirectory(basePath);

                if (!opts.ForceUpdate && Directory.Exists(outDir) &&
                    MaxWriteTime(treeFile, zipFile) < Directory.GetLastWriteTime(outDir))
                {
                    continue;
                }
                Message(TraceLevel.Warning, "Processing files: {0}, {1}", treeFile, zipFile);
                Directory.CreateDirectory(outDir);
                ExtractZipFile(zipFile, outDir);
                GenerateCache(opts, basePath, format, outDir);
            }
        }
Пример #3
0
        public override void Run(IEnumerable <string> args)
        {
            string dir         = null;
            bool   forceUpdate = false;
            var    options     = new OptionSet()
            {
                { "force-update",
                  "Always generate new files.  If not specified, will only generate " +
                  "files if the write time of the output directory is older than the " +
                  "write time of the source .tree/.zip files.",
                  v => forceUpdate = v != null },
                { "o|out=",
                  "The {PREFIX} to place the generated files and directories.  " +
                  "Default: \"`dirname FILE`/cache/\".\n" +
                  "Underneath {PREFIX}, `basename FILE .tree` directories will be " +
                  "created which will contain the pre-generated HTML content.",
                  v => dir = v },
            };
            List <string> files = Parse(options, args, "export-html-webdoc",
                                        "[OPTIONS]+ FILES",
                                        "Export mdoc documentation within FILES to HTML for use by ASP.NET webdoc.\n\n" +
                                        "FILES are .tree or .zip files as produced by 'mdoc assemble'.");

            if (files == null)
            {
                return;
            }
            if (files.Count == 0)
            {
                Error("No files specified.");
            }
            HelpSource.use_css  = true;
            HelpSource.FullHtml = false;
            SettingsHandler.Settings.EnableEditing = false;
            foreach (var basePath in
                     files.Select(f =>
                                  Path.Combine(Path.GetDirectoryName(f), Path.GetFileNameWithoutExtension(f)))
                     .Distinct())
            {
                string treeFile = basePath + ".tree";
                string zipFile  = basePath + ".zip";
                if (!Exists(treeFile) || !Exists(zipFile))
                {
                    continue;
                }
                string outDir = dir != null
                                        ? Path.Combine(dir, Path.GetFileName(basePath))
                                        : XmlDocUtils.GetCacheDirectory(basePath);

                if (!forceUpdate && Directory.Exists(outDir) &&
                    MaxWriteTime(treeFile, zipFile) < Directory.GetLastWriteTime(outDir))
                {
                    continue;
                }
                Message(TraceLevel.Warning, "Processing files: {0}, {1}", treeFile, zipFile);
                Directory.CreateDirectory(outDir);
                ExtractZipFile(zipFile, outDir);
                GenerateCache(basePath, treeFile, outDir);
            }
        }
Пример #4
0
        void GenerateCache(string basePath, string treeFile, string outDir)
        {
            Tree       tree           = new Tree(null, treeFile);
            RootTree   docRoot        = RootTree.LoadTree();
            string     helpSourceName = Path.GetFileName(basePath);
            HelpSource hs             = docRoot.HelpSources.Cast <HelpSource> ()
                                        .FirstOrDefault(h => h.Name == helpSourceName);

            if (hs == null)
            {
                throw new Exception("Only installed .tree and .zip files are supported.");
            }
            foreach (Node node in tree.TraverseDepthFirst <Node, Node> (t => t, t => t.Nodes.Cast <Node> ()))
            {
                var url = node.URL;
                Message(TraceLevel.Info, "\tProcessing URL: {0}", url);
                if (string.IsNullOrEmpty(url))
                {
                    continue;
                }
                var file = XmlDocUtils.GetCachedFileName(outDir, url);
                using (var o = File.AppendText(file)) {
                    Node _;
                    // Sometimes the HelpSource won't directly support a url.
                    // Case in point: the Tree will contain N:Enter.Namespace.Here nodes
                    // which aren't supported by HelpSource.GetText.
                    // If this happens, docRoot.RenderUrl() works.
                    // (And no, we can't always use docRoot.RenderUrl() for URLs like
                    // "ecma:0#Foo/", as that'll just grab the 0th stream contents from
                    // the first EcmaHelpSource found...
                    string contents = hs.GetText(url, out _) ?? docRoot.RenderUrl(url, out _);
                    o.Write(contents);
                }
            }
        }
Пример #5
0
        void GenerateCache(Options opts, string basePath, string format, string outDir)
        {
            var hs = RootTree.GetHelpSource(format, basePath);

            if (hs == null)
            {
                Error("Unable to find a HelpSource for provider '{0}' and file '{1}.tree'.", format, basePath);
            }
            var      tree    = hs.Tree;
            RootTree docRoot = null;

            if (!opts.UseSystemSources)
            {
                docRoot = RootTree.LoadTree(null, null, opts.Sources);
            }
            else
            {
                docRoot = RootTree.LoadTree();
                foreach (var source in opts.Sources)
                {
                    docRoot.AddSourceFile(source);
                }
            }
            hs.RootTree = docRoot;
            string helpSourceName = Path.GetFileName(basePath);

            foreach (Node node in tree.TraverseDepthFirst <Node, Node> (t => t, t => t.Nodes.Cast <Node> ()))
            {
                var url = node.URL;
                Message(TraceLevel.Info, "\tProcessing URL: {0}", url);
                if (string.IsNullOrEmpty(url))
                {
                    continue;
                }
                var file = XmlDocUtils.GetCachedFileName(outDir, url);
                using (var o = File.AppendText(file)) {
                    Node   _;
                    string contents = hs.GetText(url, out _) ?? hs.RenderNamespaceLookup(url, out _);
                    o.Write(contents);
                }
            }
        }
Пример #6
0
        static string MakeArgs(XmlElement member)
        {
            XmlNodeList parameters = member.SelectNodes("Parameters/Parameter");

            if (parameters.Count == 0)
            {
                return("");
            }
            StringBuilder args = new StringBuilder();

            args.Append("(");
            args.Append(XmlDocUtils.ToTypeName(parameters [0].Attributes ["Type"].Value, member));
            for (int i = 1; i < parameters.Count; ++i)
            {
                args.Append(",");
                args.Append(XmlDocUtils.ToTypeName(parameters [i].Attributes ["Type"].Value, member));
            }
            args.Append(")");
            return(args.ToString());
        }
Пример #7
0
        static string GetCref(XmlElement member)
        {
            string typeName = XmlDocUtils.ToEscapedTypeName(member.SelectSingleNode("/Type/@FullName").InnerText);

            if (member.Name == "Type")
            {
                return("T:" + typeName);
            }
            string memberType = member.SelectSingleNode("MemberType").InnerText;

            switch (memberType)
            {
            case "Constructor":
                return("C:" + typeName + MakeArgs(member));

            case "Event":
                return("E:" + typeName + "." + XmlDocUtils.ToEscapedMemberName(member.GetAttribute("MemberName")));

            case "Field":
                return("F:" + typeName + "." + XmlDocUtils.ToEscapedMemberName(member.GetAttribute("MemberName")));

            case "Method": {
                string name = "M:" + typeName + "." + XmlDocUtils.ToEscapedMemberName(member.GetAttribute("MemberName")) + MakeArgs(member);
                if (member.GetAttribute("MemberName") == "op_Implicit" || member.GetAttribute("MemberName") == "op_Explicit")
                {
                    name += "~" + XmlDocUtils.ToTypeName(member.SelectSingleNode("ReturnValue/ReturnType").InnerText, member);
                }
                return(name);
            }

            case "Property":
                return("P:" + typeName + "." + XmlDocUtils.ToEscapedMemberName(member.GetAttribute("MemberName")) + MakeArgs(member));

            default:
                throw new NotSupportedException("MemberType '" + memberType + "' is not supported.");
            }
        }
Пример #8
0
        void ProcessDirectories(List <string> sourceDirectories)
        {
            if (sourceDirectories.Count == 0 || opts.dest == null || opts.dest == "")
            {
                throw new ApplicationException("The source and dest options must be specified.");
            }

            Directory.CreateDirectory(opts.dest);

            // Load the stylesheets, overview.xml, and resolver

            XslCompiledTransform overviewxsl = LoadTransform("overview.xsl", sourceDirectories);
            XslCompiledTransform stylesheet  = LoadTransform("stylesheet.xsl", sourceDirectories);
            XslCompiledTransform template;

            if (opts.template == null)
            {
                template = LoadTransform("defaulttemplate.xsl", sourceDirectories);
            }
            else
            {
                try {
                    XmlDocument templatexsl = new XmlDocument();
                    templatexsl.Load(opts.template);
                    template = new XslCompiledTransform(DebugOutput);
                    template.Load(templatexsl);
                } catch (Exception e) {
                    throw new ApplicationException("There was an error loading " + opts.template, e);
                }
            }

            XmlDocument overview = GetOverview(sourceDirectories);

            ArrayList extensions = GetExtensionMethods(overview);

            // Create the master page
            XsltArgumentList overviewargs = new XsltArgumentList();

            overviewargs.AddParam("Index", "", overview.CreateNavigator());

            var regenIndex = ShouldRegenIndexes(opts, overview, sourceDirectories);

            if (regenIndex)
            {
                overviewargs.AddParam("ext", "", opts.ext);
                overviewargs.AddParam("basepath", "", "./");
                Generate(overview, overviewxsl, overviewargs, opts.dest + "/index." + opts.ext, template, sourceDirectories);
                overviewargs.RemoveParam("basepath", "");
            }
            overviewargs.AddParam("basepath", "", "../");

            // Create the namespace & type pages

            XsltArgumentList typeargs = new XsltArgumentList();

            typeargs.AddParam("ext", "", opts.ext);
            typeargs.AddParam("basepath", "", "../");
            typeargs.AddParam("Index", "", overview.CreateNavigator());

            foreach (XmlElement ns in overview.SelectNodes("Overview/Types/Namespace"))
            {
                string nsname = ns.GetAttribute("Name");

                if (opts.onlytype != null && !opts.onlytype.StartsWith(nsname + "."))
                {
                    continue;
                }

                System.IO.DirectoryInfo d = new System.IO.DirectoryInfo(opts.dest + "/" + nsname);
                if (!d.Exists)
                {
                    d.Create();
                }

                // Create the NS page
                string nsDest = opts.dest + "/" + nsname + "/index." + opts.ext;
                if (regenIndex)
                {
                    overviewargs.AddParam("namespace", "", nsname);
                    Generate(overview, overviewxsl, overviewargs, nsDest, template, sourceDirectories);
                    overviewargs.RemoveParam("namespace", "");
                }

                foreach (XmlElement ty in ns.SelectNodes("Type"))
                {
                    string typename, typefile, destfile;
                    GetTypePaths(opts, ty, out typename, out typefile, out destfile);

                    if (DestinationIsNewer(typefile, destfile))
                    {
                        // target already exists, and is newer.  why regenerate?
                        continue;
                    }

                    XmlDocument typexml = new XmlDocument();
                    typexml.Load(typefile);
                    PreserveMembersInVersions(typexml);
                    if (extensions != null)
                    {
                        DocLoader loader = CreateDocLoader(overview);
                        XmlDocUtils.AddExtensionMethods(typexml, extensions, loader);
                    }

                    Console.WriteLine(nsname + "." + typename);

                    Generate(typexml, stylesheet, typeargs, destfile, template, sourceDirectories);
                }
            }
        }
Пример #9
0
        private static void Process(string basepath, Dictionary <string, XmlElement> outputfiles, XmlDocument nsSummaries, bool implicitFiles)
        {
            if (System.Environment.CurrentDirectory == System.IO.Path.GetFullPath(basepath) && implicitFiles)
            {
                Console.WriteLine("Don't run this tool from your documentation directory, since some files could be accidentally overwritten.");
                return;
            }

            XmlDocument index_doc = new XmlDocument();

            index_doc.Load(Path.Combine(basepath, "index.xml"));
            XmlElement index = index_doc.DocumentElement;

            foreach (XmlElement assmbly in index.SelectNodes("Assemblies/Assembly"))
            {
                string assemblyName = assmbly.GetAttribute("Name");
                if (outputfiles.ContainsKey(assemblyName))
                {
                    continue;
                }
                XmlDocument output      = new XmlDocument();
                XmlElement  output_root = output.CreateElement("doc");
                output.AppendChild(output_root);

                XmlElement output_assembly = output.CreateElement("assembly");
                output_root.AppendChild(output_assembly);
                XmlElement output_assembly_name = output.CreateElement("name");
                output_assembly.AppendChild(output_assembly_name);
                output_assembly_name.InnerText = assemblyName;

                XmlElement members = output.CreateElement("members");
                output_root.AppendChild(members);

                outputfiles.Add(assemblyName, members);
            }

            foreach (XmlElement nsnode in index.SelectNodes("Types/Namespace"))
            {
                string ns = nsnode.GetAttribute("Name");
                foreach (XmlElement typedoc in nsnode.SelectNodes("Type"))
                {
                    string      typename = typedoc.GetAttribute("Name");
                    XmlDocument type     = new XmlDocument();
                    type.Load(Path.Combine(Path.Combine(basepath, ns), typename) + ".xml");

                    string     assemblyname = type.SelectSingleNode("Type/AssemblyInfo/AssemblyName").InnerText;
                    XmlElement members      = outputfiles [assemblyname];
                    if (members == null)
                    {
                        continue;                              // assembly is strangely not listed in the index
                    }
                    string typeName = XmlDocUtils.ToEscapedTypeName(type.SelectSingleNode("Type/@FullName").InnerText);
                    CreateMember("T:" + typeName, type.DocumentElement, members);

                    foreach (XmlElement memberdoc in type.SelectNodes("Type/Members/Member"))
                    {
                        string name = typeName;
                        switch (memberdoc.SelectSingleNode("MemberType").InnerText)
                        {
                        case "Constructor":
                            name = "C:" + name + MakeArgs(memberdoc);
                            break;

                        case "Method":
                            name = "M:" + name + "." + XmlDocUtils.ToEscapedMemberName(memberdoc.GetAttribute("MemberName")) + MakeArgs(memberdoc);
                            if (memberdoc.GetAttribute("MemberName") == "op_Implicit" || memberdoc.GetAttribute("MemberName") == "op_Explicit")
                            {
                                name += "~" + XmlDocUtils.ToTypeName(memberdoc.SelectSingleNode("ReturnValue/ReturnType").InnerText, memberdoc);
                            }
                            break;

                        case "Property":
                            name = "P:" + name + "." + XmlDocUtils.ToEscapedMemberName(memberdoc.GetAttribute("MemberName")) + MakeArgs(memberdoc);
                            break;

                        case "Field":
                            name = "F:" + name + "." + XmlDocUtils.ToEscapedMemberName(memberdoc.GetAttribute("MemberName"));
                            break;

                        case "Event":
                            name = "E:" + name + "." + XmlDocUtils.ToEscapedMemberName(memberdoc.GetAttribute("MemberName"));
                            break;
                        }

                        CreateMember(name, memberdoc, members);
                    }
                }
            }
            foreach (XmlElement nsnode in index.SelectNodes("Types/Namespace"))
            {
                AddNamespaceSummary(nsSummaries, basepath, nsnode.GetAttribute("Name"));
            }
        }