fill.fs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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']/Docs" with
  59. | null -> ()
  60. | mdoc ->
  61. setval mdoc "summary" "Urho's type system type."
  62. try
  63. setval mdoc "value" "StringHash representing the type for this C# type."
  64. with
  65. | ex -> ()
  66. setval mdoc "remarks" "This returns the Urho's type and is surfaced for low-level Urho code."
  67. let fillTypeName() =
  68. match doc.XPathSelectElement "Type/Members/Member[@MemberName='TypeName']/Docs" with
  69. | null -> ()
  70. | mdoc ->
  71. setval mdoc "summary" "Urho's low-level type name."
  72. try
  73. setval mdoc "value" "Stringified low-level type name."
  74. with
  75. | ex -> printfn "Problem with type %s" typeName
  76. setval mdoc "remarks" ""
  77. let fillTypeNameStatic() =
  78. match doc.XPathSelectElement "Type/Members/Member[@MemberName='TypeNameStatic']/Docs" with
  79. | null -> ()
  80. | mdoc ->
  81. setval mdoc "summary" "Urho's low-level type name, accessible as a static method."
  82. setval mdoc "value" "Stringified low-level type name."
  83. setval mdoc "remarks" ""
  84. let fillTypeStatic() =
  85. match doc.XPathSelectElement "Type/Members/Member[@MemberName='TypeStatic']/Docs" with
  86. | null -> ()
  87. | mdoc ->
  88. setval mdoc "summary" "Urho's low-level type, accessible as a static method."
  89. setval mdoc "value" "This returns the Urho's type and is surface for the low-level Urho code."
  90. setval mdoc "remarks" ""
  91. let fillTypeCtor() =
  92. match doc.XPathSelectElement "Type/Members/Member[@MemberName='.ctor']/Parameters/Parameters[@Name='handle']" with
  93. | null -> ()
  94. | pnode ->
  95. let mdoc = pnode.Parent.Parent.XPathSelectElement "Docs"
  96. setval mdoc "param[@name='handle']" "Pointer to the raw unmanaged Urho object."
  97. setval mdoc "summary" <| (sprintf "Constructs a new instance of %s, given a raw pointer to an unmanaged object" typeName)
  98. let remarks = select mdoc "remarks"
  99. remarks.RemoveAll ()
  100. XElement.Parse ("<para>This creates a new managed wrapper for the type using the raw pointer to an unmanaged object.</para>") |> remarks.Add
  101. XElement.Parse ("<para>Objects that are created in this fashion get registered with the UrhoSharp runtime.</para>") |> remarks.Add
  102. 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
  103. match doc.XPathSelectElement "Type/Members/Member[@MemberName='.ctor']/Parameters/Parameter[@Name='context' and @Type='Urho.Context']" with
  104. | null -> ()
  105. | pnodep ->
  106. let pnode = pnodep.Parent.Parent
  107. let psum = select pnode "Docs/summary"
  108. psum.RemoveAll ()
  109. XElement.Parse (sprintf "<para>Constructs a new instance of %s linked to a specific <see cref=\"T:Urho.Context\"/>.</para>" typeName) |> psum.Add
  110. setval pnode "Docs/remarks" ""
  111. match doc.XPathSelectElement "Type/Members/Member[@MemberName='.ctor']/Parameters[count(*)=0]" with
  112. | null -> ()
  113. | empty ->
  114. let emptyCtor = empty.Parent
  115. let sum = select emptyCtor "Docs/summary"
  116. sum.RemoveAll ()
  117. 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
  118. setval emptyCtor "Docs/remarks" ""
  119. let fillTypeEmpty() =
  120. for x in doc.XPathSelectElements "Type/Members/Member[@MemberName='.ctor']" do
  121. match x with
  122. | null -> ()
  123. | mem ->
  124. match mem.XPathSelectElement "Parameters/Parameter[@Name='emptyFlag']" with
  125. | null -> ()
  126. | hmember ->
  127. let mdoc = mem.XPathSelectElement "Docs"
  128. setval mdoc "param[@name='emptyFlag']" "Pass UrhoObjectFlag.Empty."
  129. setval mdoc "summary" "Empty constructor, chain to this constructor when you provide your own constructor that sets the handle field."
  130. let remarks = select mdoc "remarks"
  131. remarks.RemoveAll ()
  132. 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
  133. 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
  134. 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
  135. // For subscriptions, we like to fill in the stubs, but let the user
  136. // enter a different value if he wants to for the summary.
  137. let fillSubscribe() =
  138. for x in doc.XPathSelectElements "Type/Members/Member[ReturnValue/ReturnType = 'Urho.Subscription']" do
  139. match x with
  140. | null -> ()
  141. | m ->
  142. let name = membername m
  143. let eventName = name.Substring 11
  144. let mdoc = m.XPathSelectElement "Docs"
  145. setval mdoc "param[@name='handler']" "The handler to invoke when this event is raised."
  146. let summary = select mdoc "summary"
  147. if summary.Value = "To be added." then
  148. setval mdoc "summary" <| sprintf "Subscribes to the %s event raised by the %s (single subscriber)." eventName typeName
  149. setval mdoc "returns" "Returns an Urho.Subscription that can be used to cancel the subscription."
  150. let remarks = select mdoc "remarks"
  151. remarks.RemoveAll ()
  152. xp "<para>This method will override any prior subscription, including those assigned to on event handlers.</para>" |> remarks.Add
  153. 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
  154. sprintf "<para>For a more event-like approach, use the <see cref=\"E:%s.%s\"/> event.</para>" typeName eventName |> xp |> remarks.Add
  155. // Remember the method, so we can reference it from the event args
  156. let parameter = m.XPathSelectElement ("Parameters/Parameter[@Name='handler']")
  157. let eventArgsType = (((parameter.Attribute (xname "Type")).Value).Replace ("System.Action<Urho.","")).Replace (">","")
  158. if events.ContainsKey (eventArgsType) then
  159. ()
  160. else
  161. events.Add (eventArgsType, (eventName,typeName))
  162. // Now do the event handler
  163. // let evtNode = doc.XPathSelectElement <| sprintf "Type/Members/Member[@MemberName='%s']" eventName
  164. // For now, we do nothing.
  165. // Perhaps the master documentation for the event should live here, and the SubscribeTo can copy that.
  166. // One time use below, because after this, I went and typed manual docs.
  167. //let evtRem = select evtNode "Docs/remarks"
  168. //if evtRem.Value = "To be added." then
  169. // evtRem.RemoveAll ()
  170. // 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
  171. let fillReverse() =
  172. for x in doc.XPathSelectElements "Type/Members/Member[@MemberName='Reverse']" do
  173. match x with
  174. | null -> ()
  175. | mem ->
  176. if (mem.ToString ()).Contains ("Urho.Actions.FiniteTimeAction") then
  177. let mdoc = mem.XPathSelectElement "Docs"
  178. setval mdoc "summary" "Returns a new action that performs the exact inverse of this action."
  179. setval mdoc "remarks" ""
  180. setval mdoc "returns" "New action that will perform the inverse of this action"
  181. ()
  182. fillBaseType()
  183. fillType()
  184. fillTypeName()
  185. fillTypeNameStatic()
  186. fillTypeCtor()
  187. fillSubscribe()
  188. fillTypeStatic()
  189. //fillReverse()
  190. doc
  191. let processAction (path:string) (doc:XDocument) =
  192. let fillStartAction() =
  193. for x in doc.XPathSelectElements "Type/Members/Member[@MemberName='StartAction']" do
  194. match x with
  195. | null -> ()
  196. | mem ->
  197. if (mem.ToString ()).Contains ("Urho.Actions.ActionState") then
  198. let mdoc = mem.XPathSelectElement "Docs"
  199. setval mdoc "summary" "Creates the action state for this action, called on demand from the framework to start executing the recipe."
  200. let remarks = select mdoc "remarks"
  201. remarks.RemoveAll ()
  202. 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
  203. setval mdoc "remarks" "New action that will perform the inverse of this action"
  204. let par = match select mdoc "param[@name='target']" with
  205. | null -> select mdoc "param"
  206. | v -> v
  207. par.RemoveAll ();
  208. par.SetAttributeValue (xname "name", "target")
  209. 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
  210. ()
  211. match path.EndsWith ("State.xml"), path with
  212. | false,_ ->
  213. fillStartAction()
  214. | true, "Urho.Actions/ActionState.xml" ->
  215. ()
  216. | true, _ ->
  217. let typeDoc = doc.XPathSelectElement ("/Type")
  218. let fullName = (typeDoc.Attribute (xname "FullName")).Value
  219. let sum = doc.XPathSelectElement ("/Type/Docs/summary")
  220. sum.RemoveAll ()
  221. xp ("<para>Encapsulates the running state for the <see cref=\"T:" + fullName + "\"/> action.</para>") |> sum.Add
  222. let rem = doc.XPathSelectElement ("/Type/Docs/remarks")
  223. rem.RemoveAll ()
  224. 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
  225. doc
  226. let processShape (doc:XDocument) =
  227. match doc.XPathSelectElement "Type/Members/Member[@MemberName='.ctor']" with
  228. | null -> ()
  229. | ctor ->
  230. let summary = select ctor "Docs/summary"
  231. summary.RemoveAll ()
  232. 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
  233. setval ctor "Docs/remarks" ""
  234. match doc.XPathSelectElement "Type/Members/Member[@MemberName='ModelResource']" with
  235. | null -> ()
  236. | model ->
  237. 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."
  238. setval model "Docs/remarks" ""
  239. doc
  240. let processPath path =
  241. match load path with
  242. | null ->
  243. printfn "Problem loading %A" path
  244. ()
  245. | doc ->
  246. match path.Contains "EventArgs" with
  247. | false -> processType doc |> save path
  248. | true -> ()
  249. for xmlDoc in Directory.GetFiles ("Urho.Shapes", "*xml") do
  250. match load xmlDoc with
  251. | null -> printfn "Failed to load shape %s" xmlDoc
  252. | doc ->
  253. processShape doc |> save xmlDoc
  254. for dir in ["Urho"; "Urho.Audio"; "Urho.Gui"; "Urho.IO"; "Urho.Navigation"; "Urho.Network"; "Urho.Physics"; "Urho.Resources"; "Urho.Urho2D"] do
  255. for xmlDoc in Directory.GetFiles (dir, "*xml") do
  256. processPath xmlDoc
  257. for xmlDoc in Directory.GetFiles ("Urho.Actions", "*xml") do
  258. match load xmlDoc with
  259. | null -> printfn "Failed to load action %s" xmlDoc
  260. | doc ->
  261. processAction xmlDoc doc |> save xmlDoc
  262. for xmlDoc in Directory.GetFiles ("Urho", "*EventArgs.xml") do
  263. match load xmlDoc with
  264. | null -> printfn "Failed to load %s" xmlDoc
  265. | doc ->
  266. processEventArgs doc |> save xmlDoc