fill.fs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. open System
  2. open System.Xml
  3. open System.Xml.XPath
  4. open System.IO
  5. open System.Xml.Linq
  6. open System.Text
  7. open System.Globalization
  8. open System.Collections.Generic
  9. let load path =
  10. let f = File.OpenText path
  11. let doc = XDocument.Load f
  12. f.Close()
  13. doc
  14. let xp s =
  15. XElement.Parse (s)
  16. let events = new System.Collections.Generic.Dictionary<string,(string*string)>()
  17. let save path (doc:XDocument) =
  18. let settings = XmlWriterSettings ()
  19. settings.Indent <- true
  20. settings.Encoding <- new UTF8Encoding (false)
  21. settings.OmitXmlDeclaration <- true
  22. settings.NewLineChars <- Environment.NewLine
  23. let output = File.CreateText (path)
  24. let writer = XmlWriter.Create (output, settings)
  25. doc.Save (writer)
  26. writer.Close ()
  27. output.WriteLine ()
  28. output.Close ()
  29. let select (node:XNode) path = node.XPathSelectElement path
  30. let setval (node:XNode) path value = (select node path).Value <- value
  31. let xname s = XName.Get(s)
  32. let membername (x:XElement) =
  33. let mn = x.Attribute (xname "MemberName")
  34. mn.Value
  35. let getTypeName (doc:XDocument) =
  36. let tnode = doc.XPathSelectElement ("Type")
  37. let attr = tnode.Attribute (xname "FullName")
  38. attr.Value
  39. let processEventArgs (doc:XDocument) =
  40. let typeName = getTypeName doc
  41. let tdocs = select doc "Type/Docs"
  42. match events.ContainsKey (typeName) with
  43. | false -> ()
  44. | true ->
  45. let vals = events.[typeName]
  46. setval tdocs "summary" <| sprintf "Event arguments for the %s's %s event" (snd vals) (fst vals)
  47. doc
  48. let processType (doc:XDocument) =
  49. let typeName = getTypeName doc
  50. let fillBaseType() =
  51. match doc.XPathSelectElement "Type/Members/Member[@MemberName='BaseType']/Docs" with
  52. | null -> ()
  53. | mdoc ->
  54. setval mdoc "summary" "Urho's type system base type."
  55. setval mdoc "value" "StringHash representing the base type for this Urho type."
  56. setval mdoc "remarks" "This returns the Urho type system base type and is surfaced for low-level Urho code."
  57. let fillType() =
  58. match doc.XPathSelectElement "Type/Members/Member[@MemberName='Type']" with
  59. | null -> ()
  60. | memberType ->
  61. match memberType.XPathSelectElement "ReturnValue/ReturnType[text()= 'Urho.StringHash']" with
  62. | null -> ()
  63. | strhash ->
  64. setval memberType "Docs/summary" "Urho's type system type."
  65. try
  66. setval memberType "Docs/value" "StringHash representing the type for this C# type."
  67. with
  68. | ex -> ()
  69. setval memberType "Docs/remarks" "This returns the Urho's type and is surfaced for low-level Urho code."
  70. let fillTypeName() =
  71. match doc.XPathSelectElement "Type/Members/Member[@MemberName='TypeName']/Docs" with
  72. | null -> ()
  73. | mdoc ->
  74. setval mdoc "summary" "Urho's low-level type name."
  75. match mdoc.XPathSelectElement "value" with
  76. | null -> ()
  77. | node ->
  78. setval mdoc "value" "Stringified low-level type name."
  79. setval mdoc "remarks" ""
  80. let fillTypeNameStatic() =
  81. match doc.XPathSelectElement "Type/Members/Member[@MemberName='TypeNameStatic']/Docs" with
  82. | null -> ()
  83. | mdoc ->
  84. setval mdoc "summary" "Urho's low-level type name, accessible as a static method."
  85. setval mdoc "value" "Stringified low-level type name."
  86. setval mdoc "remarks" ""
  87. let fillTypeStatic() =
  88. match doc.XPathSelectElement "Type/Members/Member[@MemberName='TypeStatic']/Docs" with
  89. | null -> ()
  90. | mdoc ->
  91. setval mdoc "summary" "Urho's low-level type, accessible as a static method."
  92. setval mdoc "value" "This returns the Urho's type and is surface for the low-level Urho code."
  93. setval mdoc "remarks" ""
  94. let fillTypeCtor() =
  95. match doc.XPathSelectElement "Type/Members/Member[@MemberName='.ctor']/Parameters/Parameters[@Name='handle']" with
  96. | null -> ()
  97. | pnode ->
  98. let mdoc = pnode.Parent.Parent.XPathSelectElement "Docs"
  99. setval mdoc "param[@name='handle']" "Pointer to the raw unmanaged Urho object."
  100. setval mdoc "summary" <| (sprintf "Constructs a new instance of %s, given a raw pointer to an unmanaged object" typeName)
  101. let remarks = select mdoc "remarks"
  102. remarks.RemoveAll ()
  103. XElement.Parse ("<para>This creates a new managed wrapper for the type using the raw pointer to an unmanaged object.</para>") |> remarks.Add
  104. XElement.Parse ("<para>Objects that are created in this fashion get registered with the UrhoSharp runtime.</para>") |> remarks.Add
  105. XElement.Parse ("<para>This is intended to be used by the UrhoSharp runtime, and is not intended to be used by users.</para>") |> remarks.Add
  106. match doc.XPathSelectElement "Type/Members/Member[@MemberName='.ctor']/Parameters/Parameter[@Name='context' and @Type='Urho.Context']" with
  107. | null -> ()
  108. | pnodep ->
  109. let pnode = pnodep.Parent.Parent
  110. let psum = select pnode "Docs/summary"
  111. psum.RemoveAll ()
  112. XElement.Parse (sprintf "<para>Constructs a new instance of %s linked to a specific <see cref=\"T:Urho.Context\"/>.</para>" typeName) |> psum.Add
  113. setval pnode "Docs/remarks" ""
  114. match doc.XPathSelectElement "Type/Members/Member[@MemberName='.ctor']/Parameters[count(*)=0]" with
  115. | null -> ()
  116. | empty ->
  117. let emptyCtor = empty.Parent
  118. let sum = select emptyCtor "Docs/summary"
  119. sum.RemoveAll ()
  120. XElement.Parse (sprintf "<para>Constructs a new instance of %s which is tied to the <see cref=\"P:Urho.Application.CurrentContext\"/>.</para>" typeName)|> sum.Add
  121. setval emptyCtor "Docs/remarks" ""
  122. let fillTypeEmpty() =
  123. for x in doc.XPathSelectElements "Type/Members/Member[@MemberName='.ctor']" do
  124. match x with
  125. | null -> ()
  126. | mem ->
  127. match mem.XPathSelectElement "Parameters/Parameter[@Name='emptyFlag']" with
  128. | null -> ()
  129. | hmember ->
  130. let mdoc = mem.XPathSelectElement "Docs"
  131. setval mdoc "param[@name='emptyFlag']" "Pass UrhoObjectFlag.Empty."
  132. setval mdoc "summary" "Empty constructor, chain to this constructor when you provide your own constructor that sets the handle field."
  133. let remarks = select mdoc "remarks"
  134. remarks.RemoveAll ()
  135. XElement.Parse ("<para>This constructor should be invoked by your code if you provide your own constructor that sets the handle field.</para>") |> remarks.Add
  136. XElement.Parse ("<para>This essentially circumvents the default path that creates a new object and sets the handle and does not call RegisterObject on the target, you must do this on your own constructor.</para>") |> remarks.Add
  137. XElement.Parse ("<para>You would typically chain to this constructor from your own, and then set the handle to the unmanaged object from your code, and then register your object.</para>") |> remarks.Add
  138. // For subscriptions, we like to fill in the stubs, but let the user
  139. // enter a different value if he wants to for the summary.
  140. let fillSubscribe() =
  141. for x in doc.XPathSelectElements "Type/Members/Member[ReturnValue/ReturnType = 'Urho.Subscription']" do
  142. match x with
  143. | null -> ()
  144. | m ->
  145. let name = membername m
  146. let eventName = name.Substring 11
  147. let mdoc = m.XPathSelectElement "Docs"
  148. setval mdoc "param[@name='handler']" "The handler to invoke when this event is raised."
  149. let summary = select mdoc "summary"
  150. if summary.Value = "To be added." then
  151. setval mdoc "summary" <| sprintf "Subscribes to the %s event raised by the %s (single subscriber)." eventName typeName
  152. setval mdoc "returns" "Returns an Urho.Subscription that can be used to cancel the subscription."
  153. let remarks = select mdoc "remarks"
  154. remarks.RemoveAll ()
  155. xp "<para>This method will override any prior subscription, including those assigned to on event handlers.</para>" |> remarks.Add
  156. xp "<para>This has the advantage that it does a straight connection and returns a handle that is easy to unsubscribe from.</para>" |> remarks.Add
  157. sprintf "<para>For a more event-like approach, use the <see cref=\"E:%s.%s\"/> event.</para>" typeName eventName |> xp |> remarks.Add
  158. // Remember the method, so we can reference it from the event args
  159. let parameter = m.XPathSelectElement ("Parameters/Parameter[@Name='handler']")
  160. let eventArgsType = (((parameter.Attribute (xname "Type")).Value).Replace ("System.Action<Urho.","")).Replace (">","")
  161. if events.ContainsKey (eventArgsType) then
  162. ()
  163. else
  164. events.Add (eventArgsType, (eventName,typeName))
  165. // Now do the event handler
  166. // let evtNode = doc.XPathSelectElement <| sprintf "Type/Members/Member[@MemberName='%s']" eventName
  167. // For now, we do nothing.
  168. // Perhaps the master documentation for the event should live here, and the SubscribeTo can copy that.
  169. // One time use below, because after this, I went and typed manual docs.
  170. //let evtRem = select evtNode "Docs/remarks"
  171. //if evtRem.Value = "To be added." then
  172. // evtRem.RemoveAll ()
  173. // sprintf "<para>The event can register multiple callbacks and invoke all of them. If this is not desired, and you only need a single shot callback, you can use the <see cref=\"M:Urho.%s\"/> method. That one will force that callback and will ignore any previously set events here.</para>" name |> xp |> evtRem.Add
  174. let fillReverse() =
  175. for x in doc.XPathSelectElements "Type/Members/Member[@MemberName='Reverse']" do
  176. match x with
  177. | null -> ()
  178. | mem ->
  179. if (mem.ToString ()).Contains ("Urho.Actions.FiniteTimeAction") then
  180. let mdoc = mem.XPathSelectElement "Docs"
  181. setval mdoc "summary" "Returns a new action that performs the exact inverse of this action."
  182. setval mdoc "remarks" ""
  183. setval mdoc "returns" "New action that will perform the inverse of this action"
  184. ()
  185. fillBaseType()
  186. fillType()
  187. fillTypeName()
  188. fillTypeNameStatic()
  189. fillTypeCtor()
  190. fillSubscribe()
  191. fillTypeStatic()
  192. //fillReverse()
  193. doc
  194. let processAction (path:string) (doc:XDocument) =
  195. let fillStartAction() =
  196. for x in doc.XPathSelectElements "Type/Members/Member[@MemberName='StartAction']" do
  197. match x with
  198. | null -> ()
  199. | mem ->
  200. if (mem.ToString ()).Contains ("Urho.Actions.ActionState") then
  201. let mdoc = mem.XPathSelectElement "Docs"
  202. setval mdoc "summary" "Creates the action state for this action, called on demand from the framework to start executing the recipe."
  203. let remarks = select mdoc "remarks"
  204. remarks.RemoveAll ()
  205. xp "<para>The new <see cref=\"T:Urho.Actions.ActionState\"/> that encapsulates the state and provides the implementation to perform this action.</para>" |> remarks.Add
  206. setval mdoc "remarks" "New action that will perform the inverse of this action"
  207. let par = match select mdoc "param[@name='target']" with
  208. | null -> select mdoc "param"
  209. | v -> v
  210. par.RemoveAll ();
  211. par.SetAttributeValue (xname "name", "target")
  212. sprintf "<para>The new <see cref=\"T:Urho.Actions.ActionState\"/> that encapsulates the state and provides the implementation to perform your action.</para>" |> xp |> par.Add
  213. ()
  214. match path.EndsWith ("State.xml"), path with
  215. | false,_ ->
  216. fillStartAction()
  217. | true, "Urho.Actions/ActionState.xml" ->
  218. ()
  219. | true, _ ->
  220. let typeDoc = doc.XPathSelectElement ("/Type")
  221. let fullName = (typeDoc.Attribute (xname "FullName")).Value
  222. let sum = doc.XPathSelectElement ("/Type/Docs/summary")
  223. sum.RemoveAll ()
  224. xp ("<para>Encapsulates the running state for the <see cref=\"T:" + fullName + "\"/> action.</para>") |> sum.Add
  225. let rem = doc.XPathSelectElement ("/Type/Docs/remarks")
  226. rem.RemoveAll ()
  227. xp ("<para>This object is created on demand when the action starts executing on a node, and it tracks the state of the action as it executes.</para>") |> rem.Add
  228. doc
  229. let processShape (doc:XDocument) =
  230. match doc.XPathSelectElement "Type/Members/Member[@MemberName='.ctor']" with
  231. | null -> ()
  232. | ctor ->
  233. let summary = select ctor "Docs/summary"
  234. summary.RemoveAll ()
  235. xp "<para>Constructs an instance of the type, for internal use. These types are created by calling <see cref=\"M:Urho.Node.CreateComponent\"/></para>" |> summary.Add
  236. setval ctor "Docs/remarks" ""
  237. match doc.XPathSelectElement "Type/Members/Member[@MemberName='ModelResource']" with
  238. | null -> ()
  239. | model ->
  240. setval model "Docs/summary" "Returns the path of the model for this shape, for the shape to work, the MDL file in the CoreData package must exist."
  241. setval model "Docs/remarks" ""
  242. doc
  243. let processPath path =
  244. match load path with
  245. | null ->
  246. printfn "Problem loading %A" path
  247. ()
  248. | doc ->
  249. match path.Contains "EventArgs" with
  250. | false -> processType doc |> save path
  251. | true -> ()
  252. for xmlDoc in Directory.GetFiles ("Urho.Shapes", "*xml") do
  253. match load xmlDoc with
  254. | null -> printfn "Failed to load shape %s" xmlDoc
  255. | doc ->
  256. processShape doc |> save xmlDoc
  257. for dir in ["Urho"; "Urho.Audio"; "Urho.Gui"; "Urho.IO"; "Urho.Navigation"; "Urho.Network"; "Urho.Physics"; "Urho.Resources"; "Urho.Urho2D"] do
  258. for xmlDoc in Directory.GetFiles (dir, "*xml") do
  259. processPath xmlDoc
  260. for xmlDoc in Directory.GetFiles ("Urho.Actions", "*xml") do
  261. match load xmlDoc with
  262. | null -> printfn "Failed to load action %s" xmlDoc
  263. | doc ->
  264. processAction xmlDoc doc |> save xmlDoc
  265. for xmlDoc in Directory.GetFiles ("Urho", "*EventArgs.xml") do
  266. match load xmlDoc with
  267. | null -> printfn "Failed to load %s" xmlDoc
  268. | doc ->
  269. processEventArgs doc |> save xmlDoc