build/scripts/XmlDocPatcher.fs (78 lines of code) (raw):

// Licensed to Elasticsearch B.V under one or more agreements. // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. namespace Scripts open System open System.Linq open System.Text.RegularExpressions open System.Xml open System.Xml.Linq open System.Xml.XPath module InheritDoc = let private apiName n = Regex.Replace(n, @"^\w\:(.+?)(?:\(.+$|$)", "$1") let private relatedInterface n = Regex.Replace(n, @"\.([^.]+\.[^.]+)$", ".I$1") let private relatedInterfaceAsync n = (relatedInterface n).Replace("Async", "") let private relatedInterfaceDescriptor n = Regex.Replace(n, @"\.([^.]+)Descriptor\.([^.]+)$", ".I$1.$2") let private relatedInterfaceDescriptorRequest n = Regex.Replace(n, @"\.([^.]+)Descriptor\.([^.]+)$", ".I$1Request.$2") let private relatedInterfaceDescriptorGeneric n = Regex.Replace(n, @"\.([^.]+)Descriptor[^.]+.([^.]+)$", ".I$1.$2") let private manualMapping (n : string) = //this sucks but untill roslyn gets coderewriting API's this is the best we got without making it //a bigger thing than it already is match n with | n when n.Contains("PutMapping") -> n.Replace("PutMapping", "TypeMapping") | _ -> n let private relatedApiLookups = [ relatedInterface; relatedInterfaceAsync; relatedInterfaceDescriptor; relatedInterfaceDescriptorRequest; relatedInterfaceDescriptorGeneric; manualMapping ] let private documentedApis (file:string) = use reader = XmlReader.Create file seq { while reader.ReadToFollowing("member") do let name = apiName(reader.GetAttribute("name")) let innerXml = reader.ReadInnerXml().Trim(); if (not (String.IsNullOrEmpty innerXml) && not (innerXml.Contains("<inheritdoc"))) then let xdoc = XDocument.Parse("<x>" + innerXml + "</x>") yield (name, xdoc) } |> Map.ofSeq let private patchInheritDoc file = printfn "Rewriting xmldoc: %s" file let mapOfDocumentedApis = documentedApis file let findDocumentation (apiElement:string) = relatedApiLookups |> Seq.map (fun f -> f apiElement) |> (Seq.map <| mapOfDocumentedApis.TryFind) |> Seq.choose id |> Seq.tryHead let xml = XDocument.Load file xml.XPathSelectElements("//inheritdoc") |> Seq.iter (fun inheritDocElement -> let parent =inheritDocElement.Parent let name = apiName (parent.Attribute(XName.Get "name").Value) let documentation = findDocumentation name match documentation with | Some d -> let elements = d.Element(XName.Get("x")).Elements().ToList(); inheritDocElement.AddBeforeSelf(elements) | _ -> //unignore the following to find undocumented/badly inherited methods //tracefn "not inherited: %s" apiElement ignore() ) use writer = new XmlTextWriter(file,null) writer.Formatting <- Formatting.Indented; xml.Save(writer); let PatchInheritDocs() = ignore() //TODO VALIDATE this still works as expected // AllPublishableProjectsWithSupportedFrameworks // |> Seq.map (fun p -> // let folder = Paths.ProjectOutputFolder p.project p.framework // Path.Combine(folder, p.project.Name) + ".xml" // ) // |> Seq.filter File.Exists // |> Seq.iter patchInheritDoc