Skip to content

Commit 4389931

Browse files
committed
Merge pull request microsoft#2 from Microsoft/makePREasier
Refactor to make sending PR easier
2 parents bfb9db0 + e0f8c27 commit 4389931

File tree

8 files changed

+533
-399
lines changed

8 files changed

+533
-399
lines changed

JS.fs

Lines changed: 75 additions & 75 deletions
Large diffs are not rendered by default.

Program.fs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11

22
[<EntryPoint>]
33
let main argv =
4-
JS.DumpDomWeb()
5-
JS.DumpDomWin()
6-
JS.DumpDomWorker()
4+
JS.EmitDomWeb()
5+
JS.EmitDomWin()
6+
JS.EmitDomWorker()
77
// For typescript only generate for Dom
8-
TS.DumpDomWeb()
9-
TS.DumpDomWorker()
8+
TS.EmitDomWeb()
9+
TS.EmitDomWorker()
1010
0

README.md

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# CreateDomJSTS
2-
This tool is used to generate the DOM related part of `lib.d.ts` for TypeScript, and `domWeb.js` and `domWindows.js` for Visual Studio JavaScript language service. The input file is the XML spec file generated by the Microsoft Edge browser.
1+
# TypeScript and JavaScript lib generator
2+
This tool is used to generate `dom.generated.d.ts` and `webworker.generated.d.ts` for TypeScript, and `domWeb.js` and `domWindows.js` for Visual Studio JavaScript language service. The input file is the XML spec file generated by the Microsoft Edge browser.
33

44
## Build Instruction
55
**Required Software**: Visual Studio 2015 Community Version (with Visual F# installed)
@@ -14,9 +14,13 @@ Press `F5` in Visual Studio to run the tool. If it runs successfully, the output
1414
- `JS.fs`: handles the emitting of the `domWeb.js` and `domWindows.js`
1515
files used for Visual Studio JavaScript language service;
1616
- `Program.fs`: entry point of the tool;
17-
- Inside the `inputfiles` folder:
18-
- `browser.webidl.xml`: the XML spec file generated by Microsoft Edge (due to the different updating schedules between Edge and TypeScript, this is **not** the most up-to-date version of the spec);
19-
- `jsTemplate.js`: the initial templates for `domWeb.js` and `domWindows.js`, which contains the necessary helper functions;
20-
- `additionalSharedTypes.ts`: types should exist in both browser and webworker that are missing from the Edge spec.
21-
- `additionalDomTypes.ts`: types should exist in only browser that are missing from the Edge spec.
22-
- `additionalWorkerTypes.ts`: types should exist in only webworker that are missing from the Edge spec.
17+
18+
## Input Files:
19+
- `browser.webidl.xml`: the XML spec file generated by Microsoft Edge (due to the different updating schedules between Edge and TypeScript, this may **not** be the most up-to-date version of the spec.);
20+
- `webworker.webidl.xml`: contains additional types for webworker.
21+
- `addedTypes.json`: types that should exist in either browser or webworker but are missing from the Edge spec. The type can be `property`, `method`, `interface`, `constructor`, or `indexer`.
22+
- `overridingTypes.json`: types that are defined in the spec file but has a better or more up-to-date definitions in the json files.
23+
- `removedTypes.json`: types that are defined in the spec file but should be removed.
24+
- `comments.json`: comment strings to be embedded in the generated .js files
25+
- `jsTemplate.js`: the initial templates for `domWeb.js` and `domWindows.js`, which contains the necessary helper functions;
26+
- `sample.json`: sample json file used to tell F# json type provider that structure of the json files. The content of it is not used anywhere.

Shared.fs

Lines changed: 99 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -26,62 +26,91 @@ module GlobalVars =
2626
/// ===========================================
2727
/// Types
2828
/// ===========================================
29+
30+
/// Quick checker for option type values
31+
let OptionCheckValue value = function
32+
| Some v when v = value -> true
33+
| _ -> false
34+
35+
let unionToString (x: 'a) =
36+
match FSharpValue.GetUnionFields(x, typeof<'a>) with
37+
| case, _ -> case.Name
38+
2939
type Flavor =
3040
| Worker
3141
| Web
32-
| Windows
33-
override x.ToString() =
34-
match FSharpValue.GetUnionFields(x, typeof<Flavor>) with
35-
| case, _ -> case.Name
42+
| All
43+
override x.ToString() = unionToString x
44+
45+
type Browser = XmlProvider<"sample.xml", Global=true>
46+
47+
module JsonItems =
48+
type ItemsType = JsonProvider<"inputfiles/sample.json">
3649

37-
type Browser = XmlProvider< "sample.xml", Global=true >
50+
let overriddenItems =
51+
File.ReadAllText(GlobalVars.inputFolder + @"\overridingTypes.json") |> ItemsType.Parse
3852

39-
type CommentType = JsonProvider<"inputfiles/comments.json">
53+
let removedItems =
54+
File.ReadAllText(GlobalVars.inputFolder + @"\removedTypes.json") |> ItemsType.Parse
4055

41-
type TypesFromJsonFile = JsonProvider<"inputfiles/sample.json">
56+
let addedItems =
57+
File.ReadAllText(GlobalVars.inputFolder + @"\addedTypes.json") |> ItemsType.Parse
4258

43-
let overridingTypes =
44-
File.ReadAllText(__SOURCE_DIRECTORY__ + @"\inputfiles\overridingTypes.json") |> TypesFromJsonFile.Parse
59+
// This is the kind of items in the external json files that are used as a
60+
// correction for the spec.
61+
type ItemKind =
62+
Property | Method | Constant | Constructor | Interface | Callback | Indexer
63+
override x.ToString() = (unionToString x).ToLower()
4564

46-
let removedTypes =
47-
File.ReadAllText(__SOURCE_DIRECTORY__ + @"\inputfiles\removedTypes.json") |> TypesFromJsonFile.Parse
65+
let findItem (allItems: ItemsType.Root []) (itemName: string) (kind: ItemKind) otherFilter =
66+
let filter (item: ItemsType.Root) =
67+
OptionCheckValue itemName item.Name &&
68+
item.Kind.ToLower() = kind.ToString() &&
69+
otherFilter item
70+
allItems |> Array.tryFind filter
4871

49-
let addedTypes =
50-
File.ReadAllText(__SOURCE_DIRECTORY__ + @"\inputfiles\addedTypes.json") |> TypesFromJsonFile.Parse
72+
let matchInterface iName (item: ItemsType.Root) =
73+
item.Interface.IsNone || item.Interface.Value = iName
5174

52-
type MemberKind =
53-
Property | Method
54-
member this.ToString = if this = Property then "property" else "method"
75+
let findOverriddenItem itemName (kind: ItemKind) iName =
76+
findItem overriddenItems itemName kind (matchInterface iName)
5577

56-
let findTypeFromJsonArray (jsonArray: TypesFromJsonFile.Root []) mName iName (kind: MemberKind) =
57-
jsonArray
58-
|> Array.tryFind (fun t ->
59-
t.Name = mName && (t.Interface.IsNone || t.Interface.Value = iName) && t.Kind = kind.ToString)
78+
let findRemovedItem itemName (kind: ItemKind) iName =
79+
findItem removedItems itemName kind (matchInterface iName)
6080

61-
let findOverridingType mName iName (kind: MemberKind) = findTypeFromJsonArray overridingTypes mName iName kind
62-
let findRemovedType mName iName (kind: MemberKind) = findTypeFromJsonArray removedTypes mName iName kind
63-
let findAddedType mName iName (kind: MemberKind) = findTypeFromJsonArray addedTypes mName iName kind
81+
let findAddedItem itemName (kind: ItemKind) iName =
82+
findItem addedItems itemName kind (matchInterface iName)
6483

65-
let getAllAddedInterfaces (flavor: Flavor) =
66-
addedTypes |> Array.filter (fun t -> t.Kind = "interface" && (t.Flavor.IsNone || t.Flavor.Value = flavor.ToString() || flavor = Windows))
84+
let getItems (allItems: ItemsType.Root []) (kind: ItemKind) (flavor: Flavor) =
85+
allItems
86+
|> Array.filter (fun t ->
87+
t.Kind.ToLower() = kind.ToString() &&
88+
(t.Flavor.IsNone || t.Flavor.Value = flavor.ToString() || flavor = All))
6789

68-
let comments = File.ReadAllText(__SOURCE_DIRECTORY__ + @"\inputfiles\comments.json") |> CommentType.Parse
90+
let getOverriddenItems kind flavor = getItems overriddenItems kind flavor
91+
let getAddedItems kind flavor = getItems addedItems kind flavor
92+
let getRemovedItems kind flavor = getItems removedItems kind flavor
6993

70-
let GetCommentForProperty iName pName =
71-
match comments.Interfaces |> Array.tryFind (fun i -> i.Name = iName) with
72-
| Some i ->
73-
match i.Members.Property |> Array.tryFind (fun p -> p.Name = pName) with
74-
| Some p -> Some p.Comment
94+
module Comments =
95+
type CommentType = JsonProvider<"inputfiles/comments.json">
96+
97+
let comments = File.ReadAllText(__SOURCE_DIRECTORY__ + @"\inputfiles\comments.json") |> CommentType.Parse
98+
99+
let GetCommentForProperty iName pName =
100+
match comments.Interfaces |> Array.tryFind (fun i -> i.Name = iName) with
101+
| Some i ->
102+
match i.Members.Property |> Array.tryFind (fun p -> p.Name = pName) with
103+
| Some p -> Some p.Comment
104+
| _ -> None
75105
| _ -> None
76-
| _ -> None
77106

78-
let GetCommentForMethod iName mName =
79-
match comments.Interfaces |> Array.tryFind (fun i -> i.Name = iName) with
80-
| Some i ->
81-
match i.Members.Method |> Array.tryFind (fun m -> m.Name = mName) with
82-
| Some m -> Some m.Comment
107+
let GetCommentForMethod iName mName =
108+
match comments.Interfaces |> Array.tryFind (fun i -> i.Name = iName) with
109+
| Some i ->
110+
match i.Members.Method |> Array.tryFind (fun m -> m.Name = mName) with
111+
| Some m -> Some m.Comment
112+
| _ -> None
83113
| _ -> None
84-
| _ -> None
85114

86115
// Printer for print to file
87116
type Printer(target : TextWriter) =
@@ -107,7 +136,7 @@ type Printer(target : TextWriter) =
107136
member this.printWithAddedIndent content =
108137
Printf.kprintf (fun s -> output.Append("\r\n" + this.getCurIndent() + " " + s) |> ignore) content
109138

110-
member this.dump() =
139+
member this.emit() =
111140
fprintf this.target "%s" (output.ToString())
112141
this.target.Flush()
113142

@@ -163,20 +192,23 @@ type EventHandler =
163192
EventName : string
164193
EventType : string }
165194

166-
/// Decide which members of a function to dump
167-
type DumpScope =
195+
/// Decide which members of a function to emit
196+
type EmitScope =
168197
| StaticOnly
169198
| InstanceOnly
170199
| All
171200

172201
// Used to decide if a member should be emitted given its static property and
173202
// the intended scope level.
174-
let inline matchScope scope (x: ^a when ^a: (member Static: Option<int>)) =
175-
if scope = DumpScope.All then true
203+
let inline matchScope scope (x: ^a when ^a: (member Static: Option<'b>)) =
204+
if scope = EmitScope.All then true
176205
else
177-
let isStatic = (^a: (member Static: Option<int>)x)
178-
if isStatic.IsSome then scope = DumpScope.StaticOnly
179-
else scope = DumpScope.InstanceOnly
206+
let isStatic = (^a: (member Static: Option<'b>)x)
207+
if isStatic.IsSome then scope = EmitScope.StaticOnly
208+
else scope = EmitScope.InstanceOnly
209+
210+
let matchInterface iName (x: JsonItems.ItemsType.Root) =
211+
x.Interface.IsNone || x.Interface.Value = iName
180212

181213
/// ===========================================
182214
/// Shared data and helper functions
@@ -198,11 +230,6 @@ let AdjustParamName name =
198230
| "continue" -> "_continue"
199231
| _ -> name
200232

201-
/// Quick checker for option type values
202-
let OptionCheckValue value = function
203-
| Some v when v = value -> true
204-
| _ -> false
205-
206233
/// Parse the xml input file
207234
let browser =
208235
(new StreamReader(Path.Combine(GlobalVars.inputFolder, "browser.webidl.xml"))).ReadToEnd() |> Browser.Parse
@@ -214,18 +241,18 @@ let worker =
214241
/// (Member constraint aka duck typing)
215242
/// reason is that ^a can be an interface, property or method, but they
216243
/// all share a 'tag' property
217-
let inline ShouldKeep flavor (i : ^a when ^a : (member Tags : string option) and ^a : (member Name : string)) =
244+
let inline ShouldKeep flavor (i : ^a when ^a : (member Tags : string option)) =
218245
let filterByTag =
219246
match ((((((^a : (member Tags : string option) i)))))) with
220247
| Some tags ->
221248
// Check if should be included
222249
match flavor with
223-
| Web ->
250+
| Flavor.Web ->
224251
[ "MSAppOnly"; "WinPhoneOnly" ]
225252
|> Seq.exists (fun t -> tags.Contains t)
226253
|> not
227-
| Windows -> true
228-
| Worker ->
254+
| Flavor.All -> true
255+
| Flavor.Worker ->
229256
[ "IEOnly" ]
230257
|> Seq.exists (fun t -> tags.Contains t)
231258
|> not
@@ -277,29 +304,32 @@ let knownWorkerInterfaces =
277304

278305
let GetAllInterfacesByFlavor flavor =
279306
match flavor with
280-
| Web -> allWebInterfaces |> Array.filter (ShouldKeep Web)
281-
| Windows -> allWebInterfaces |> Array.filter (ShouldKeep Windows)
282-
| Worker ->
307+
| Flavor.Web -> allWebInterfaces |> Array.filter (ShouldKeep Web)
308+
| Flavor.All -> allWebInterfaces |> Array.filter (ShouldKeep Flavor.All)
309+
| Flavor.Worker ->
283310
let isFromBrowserXml = allWebInterfaces |> Array.filter (fun i -> knownWorkerInterfaces.Contains i.Name)
284311
Array.append isFromBrowserXml allWorkerAdditionalInterfaces
285312

286313
let GetNonCallbackInterfacesByFlavor flavor =
287314
match flavor with
288-
| Web -> allWebNonCallbackInterfaces |> Array.filter (ShouldKeep Web)
289-
| Windows -> allWebNonCallbackInterfaces |> Array.filter (ShouldKeep Windows)
290-
| Worker ->
315+
| Flavor.Web -> allWebNonCallbackInterfaces |> Array.filter (ShouldKeep Flavor.Web)
316+
| Flavor.All -> allWebNonCallbackInterfaces |> Array.filter (ShouldKeep Flavor.All)
317+
| Flavor.Worker ->
291318
let isFromBrowserXml =
292319
allWebNonCallbackInterfaces |> Array.filter (fun i -> knownWorkerInterfaces.Contains i.Name)
293320
Array.append isFromBrowserXml allWorkerAdditionalInterfaces
294321

295322
let GetPublicInterfacesByFlavor flavor =
296323
match flavor with
297-
| Web | Windows -> browser.Interfaces |> Array.filter (ShouldKeep flavor)
298-
| Worker ->
324+
| Flavor.Web | Flavor.All -> browser.Interfaces |> Array.filter (ShouldKeep flavor)
325+
| Flavor.Worker ->
299326
let isFromBrowserXml = browser.Interfaces |> Array.filter (fun i -> knownWorkerInterfaces.Contains i.Name)
300327
Array.append isFromBrowserXml worker.Interfaces
301328

302-
let GetCallbackFuncsByFlavor flavor = browser.CallbackFunctions |> Array.filter (ShouldKeep flavor)
329+
let GetCallbackFuncsByFlavor flavor =
330+
browser.CallbackFunctions
331+
|> Array.filter (ShouldKeep flavor)
332+
|> Array.filter (fun cb -> flavor <> Flavor.Worker || knownWorkerInterfaces.Contains cb.Name)
303333

304334
/// Event name to event type map
305335
let eNameToEType =
@@ -342,7 +372,7 @@ let tagNameToEleName =
342372
| name when Seq.contains name iNames -> name
343373
| _ -> raise (Exception("Element conflict occured! Typename: " + tagName))
344374

345-
[ for i in GetNonCallbackInterfacesByFlavor Windows do
375+
[ for i in GetNonCallbackInterfacesByFlavor Flavor.All do
346376
yield! [ for e in i.Elements do
347377
yield (e.Name, i.Name) ] ]
348378
|> Seq.groupBy fst
@@ -380,15 +410,15 @@ let iNameToIDependList =
380410
/// Distinct event type list, used in the "createEvent" function
381411
let distinctETypeList =
382412
let usedEvents =
383-
[ for i in GetNonCallbackInterfacesByFlavor Windows do
413+
[ for i in GetNonCallbackInterfacesByFlavor Flavor.All do
384414
match i.Events with
385415
| Some es -> yield! es.Events
386416
| _ -> () ]
387417
|> List.map (fun e -> e.Type)
388418
|> List.distinct
389419

390420
let unUsedEvents =
391-
GetNonCallbackInterfacesByFlavor Windows
421+
GetNonCallbackInterfacesByFlavor Flavor.All
392422
|> Array.filter (fun i -> i.Extends = "Event")
393423
|> Array.map (fun i -> i.Name)
394424
|> Array.filter (fun n -> n.EndsWith("Event") && not (List.contains n usedEvents))
@@ -475,8 +505,8 @@ let ehNameToEType =
475505

476506
let GetGlobalPollutor flavor =
477507
match flavor with
478-
| Web | Windows -> browser.Interfaces |> Array.tryFind (fun i -> i.PrimaryGlobal.IsSome)
479-
| Worker -> worker.Interfaces |> Array.tryFind (fun i -> i.Global.IsSome)
508+
| Flavor.Web | Flavor.All -> browser.Interfaces |> Array.tryFind (fun i -> i.PrimaryGlobal.IsSome)
509+
| Flavor.Worker -> worker.Interfaces |> Array.tryFind (fun i -> i.Global.IsSome)
480510

481511
let GetGlobalPollutorName flavor =
482512
match GetGlobalPollutor flavor with

0 commit comments

Comments
 (0)