Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: utils/apidoc/mdn/postProcess.dart

Issue 9360002: cleanup postProcess step and output obsolete.json file (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #library("postProcess"); 1 #library("postProcess");
2 2
3 #import("../../../frog/lib/node/node.dart"); 3 #import("../../../frog/lib/node/node.dart");
4 #import("dart:json"); 4 #import("dart:json");
5 #import("util.dart");
5 6
6 // TODO(jacobr): this file conflates pretty printing of the JSON database with 7 void main() {
7 // filtering the database to select the best matches per file. 8 // Database of code documentation.
8 // Separate out the two tasks as quick and dirty coding is correct for pretty 9 Map<String, List> database = JSON.parse(
9 // printing but more carefully documented code is required for the code 10 fs.readFileSync('output/database.json', 'utf8'));
10 // filtering the database. 11 final filteredDb = {};
11 Map<String, List> database; 12 final obsolete = [];
12 Map<String, Map> allProps; 13 for (String type in database.getKeys()) {
13 Set<String> matchedTypes; 14 final entry = pickBestEntry(database[type], type);
14 15 filteredDb[type] = entry;
15 String orEmpty(String str) { 16 if (entry.containsKey("members")) {
16 return str == null ? "" : str; 17 Map members = getMembersMap(entry);
17 } 18 for (String name in members.getKeys()) {
18 19 Map memberData = members[name];
19 /** Returns whether the type has any member matching the specified name. */ 20 if (memberData['obsolete'] == true) {
20 bool hasAny(String type, String prop) { 21 obsolete.add({'type': type, 'member' : name});
21 final data = allProps[type];
22 return data['properties'].containsKey(prop) ||
23 data['methods'].containsKey(prop) ||
24 data['constants'].containsKey(prop);
25 }
26
27 List<String> sortStringCollection(Collection<String> collection) {
28 final out = <String>[];
29 out.addAll(collection);
30 out.sort((String a, String b) => a.compareTo(b));
31 return out;
32 }
33
34 /**
35 * Return the members from an [entry] as Map of member names to member
36 * objects.
37 */
38 Map getMembersMap(Map entry) {
39 List<Map> rawMembers = entry["members"];
40 final members = {};
41 for (final entry in rawMembers) {
42 members[entry['name']] = entry;
43 }
44 return members;
45 }
46
47 int addMissing(StringBuffer sb, String type, Map members) {
48 int total = 0;
49 /**
50 * Add all missing members to the string output and return the number of
51 * missing members.
52 */
53 void addMissingHelper(String propType) {
54 Map expected = allProps[type][propType];
55 if (expected != null) {
56 for(final name in sortStringCollection(expected.getKeys())) {
57 if (!members.containsKey(name)) {
58 total++;
59 sb.add("""
60 <tr class="missing">
61 <td>$name</td>
62 <td></td>
63 <td>Could not find documentation for $propType</td>
64 </tr>
65 """);
66 } 22 }
67 } 23 }
68 } 24 }
69 } 25 }
70
71 addMissingHelper('properties');
72 addMissingHelper('methods');
73 addMissingHelper('constants');
74 return total;
75 }
76
77 /**
78 * Score entries using similarity heuristics calculated from the observed and
79 * expected list of members. We could be much less naive and penalize spurious
80 * methods, prefer entries with class level comments, etc. This method is
81 * needed becase we extract entries for each of the top search results for
82 * each class name and rely on these scores to determine which entry was
83 * best. Typically all scores but one will be zero. Multiple pages have
84 * non-zero scores when MDN has multiple pages on the same class or pages on
85 * similar classes (e.g. HTMLElement and Element), or pages on Mozilla
86 * specific classes that are similar to DOM classes (Console).
87 */
88 num scoreEntry(Map entry, String type) {
89 num score = 0;
90 // TODO(jacobr): consider removing skipped entries completely instead of
91 // just giving them lower scores.
92 if (!entry.containsKey('skipped')) {
93 score++;
94 }
95 if (entry.containsKey("members")) {
96 Map members = getMembersMap(entry);
97 for (String name in members.getKeys()) {
98 if (hasAny(type, name)) {
99 score++;
100 }
101 }
102 }
103 return score;
104 }
105
106 /**
107 * Given a list of candidates for the documentation for a type, find the one
108 * that is the best.
109 */
110 Map pickBestEntry(List entries, String type) {
111 num bestScore = -1;
112 Map bestEntry;
113 for (Map entry in entries) {
114 if (entry != null) {
115 num score = scoreEntry(entry, type);
116 if (score > bestScore) {
117 bestScore = score;
118 bestEntry = entry;
119 }
120 }
121 }
122 return bestEntry;
123 }
124
125 void main() {
126 // Database of code documentation.
127 database = JSON.parse(fs.readFileSync('output/database.json', 'utf8'));
128 // Database of expected property names for each type in WebKit.
129 allProps = JSON.parse(fs.readFileSync('data/dartIdl.json', 'utf8'));
130 // Types we have documentation for.
131 matchedTypes = new Set<String>();
132 int numMissingMethods = 0;
133 int numFoundMethods = 0;
134 int numExtraMethods = 0;
135 int numGen = 0;
136 int numSkipped = 0;
137 final sbSkipped = new StringBuffer();
138 final sbAllExamples = new StringBuffer();
139 final filteredDb = {};
140
141 // Table rows for all obsolete members.
142 final sbObsolete = new StringBuffer();
143 // Main documentation file.
144 final sb = new StringBuffer();
145
146 // TODO(jacobr): switch to using a real template system instead of string
147 // interpolation combined with StringBuffers.
148 sb.add("""
149 <html>
150 <head>
151 <style type="text/css">
152 body {
153 background-color: #eee;
154 margin: 10px;
155 font: 14px/1.428 "Lucida Grande", "Lucida Sans Unicode", Lucida,
156 Arial, Helvetica, sans-serif;
157 }
158
159 .debug {
160 color: #888;
161 }
162
163 .compatibility, .links, .see-also, .summary, .members, .example {
164 border: 1px solid #CCC;
165 margin: 5px;
166 padding: 5px;
167 }
168
169 .type, #dart_summary {
170 border: 1px solid;
171 margin-top: 10px;
172 margin-bottom: 10px;
173 padding: 10px;
174 overflow: hidden;
175 background-color: white;
176 -moz-box-shadow: 5px 5px 5px #888;
177 -webkit-box-shadow: 5px 5px 5px #888;
178 box-shadow: 5px 5px 5px #888;
179 }
180
181 #dart_summary {
182 border: 2px solid #00F;
183 margin: 5px;
184 padding: 5px;
185 }
186
187 th {
188 background-color:#ccc;
189 font-weight: bold;
190 }
191
192 tr:nth-child(odd) {
193 background-color:#eee;
194 }
195 tr:nth-child(even) {
196 background-color:#fff;
197 }
198
199 tr:nth-child(odd).unknown {
200 background-color:#dd0;
201 }
202 tr:nth-child(even).unknown {
203 background-color:#ff0;
204 }
205
206 tr:nth-child(odd).missing {
207 background-color:#d88;
208 }
209 tr:nth-child(even).missing {
210 background-color:#faa;
211 }
212
213 li.unknown {
214 color: #f00;
215 }
216
217 td, th {
218 vertical-align: top;
219 }
220 </style>
221 <title>Doc Dump</title>
222 </head>
223 <body>
224 <h1>Doc Dump</h1>
225 <ul>
226 <li><a href="#dart_summary">Summary</a></li>
227 </li>
228 """);
229
230 for (String type in sortStringCollection(database.getKeys())) {
231 Map entry = pickBestEntry(database[type], type);
232 filteredDb[type] = entry;
233 if (entry == null || entry.containsKey('skipped')) {
234 numSkipped++;
235 sbSkipped.add("""
236 <li id="$type">
237 <a target="_blank" href="http://www.google.com/cse?cx=01719397256594783026 6%3Awpqsk6dy6ee&ie=UTF-8&q=$type">
238 $type
239 </a>
240 --
241 Title: ${entry == null ? "???" : entry["title"]} -- Issue:
242 ${entry == null ? "???" : entry['cause']}
243 --
244 <a target="_blank" href="${entry == null ? "???" : entry["srcUrl"]}">
245 scraped url
246 </a>
247 </li>""");
248 continue;
249 }
250 matchedTypes.add(type);
251 numGen++;
252 StringBuffer sbSections = new StringBuffer();
253 StringBuffer sbMembers = new StringBuffer();
254 StringBuffer sbExamples = new StringBuffer();
255 if (entry.containsKey("members")) {
256 Map members = getMembersMap(entry);
257 sbMembers.add("""
258 <div class="members">
259 <h3><span class="debug">[dart]</span> Members</h3>
260 <table>
261 <tbody>
262 <tr>
263 <th>Name</th><th>Description</th><th>IDL</th><th>Status</th>
264 </tr>
265 """);
266 for (String name in sortStringCollection(members.getKeys())) {
267 Map memberData = members[name];
268 bool unknown = !hasAny(type, name);
269 StringBuffer classes = new StringBuffer();
270 if (unknown) classes.add("unknown ");
271 if (unknown) {
272 numExtraMethods++;
273 } else {
274 numFoundMethods++;
275 }
276
277 final sbMember = new StringBuffer();
278
279 if (memberData.containsKey('url')) {
280 sbMember.add("""
281 <td><a href="${memberData['url']}">$name</a></td>
282 """);
283 } else {
284 sbMember.add("""
285 <td>$name</td>
286 """);
287 }
288 sbMember.add("""
289 <td>${memberData['help']}</td>
290 <td>
291 <pre>${orEmpty(memberData['idl'])}</pre>
292 </td>
293 <td>${memberData['obsolete'] == true ? "Obsolete" : ""}</td>
294 """);
295 if (memberData['obsolete'] == true) {
296 sbObsolete.add("<tr class='$classes'><td>$type</td>$sbMember</tr>");
297 }
298 sbMembers.add("<tr class='$classes'>$sbMember</tr>");
299 }
300
301 numMissingMethods += addMissing(sbMembers, type, members);
302
303 sbMembers.add("""
304 </tbody>
305 </table>
306 </div>
307 """);
308 }
309 for (String sectionName in
310 ["summary", "constructor", "compatibility", "specification",
311 "seeAlso"]) {
312 if (entry.containsKey(sectionName)) {
313 sbSections.add("""
314 <div class="$sectionName">
315 <h3><span class="debug">[Dart]</span> $sectionName</h3>
316 ${entry[sectionName]}
317 </div>
318 """);
319 }
320 }
321 if (entry.containsKey("links")) {
322 sbSections.add("""
323 <div class="links">
324 <h3><span class="debug">[Dart]</span> Specification</h3>
325 <ul>
326 """);
327 List links = entry["links"];
328 for (Map link in links) {
329 sbSections.add("""
330 <li><a href="${link['href']}">${link['title']}</a></li>
331 """);
332 }
333 sbSections.add("""
334 </ul>
335 </div>
336 """);
337 }
338 if (entry.containsKey("examples")) {
339 for (String example in entry["examples"]) {
340 sbExamples.add("""
341 <div class="example">
342 <h3><span class="debug">[Dart]</span> Example</h3>
343 $example
344 </div>
345 """);
346 }
347 }
348
349 String title = entry['title'];
350 if (title != type) {
351 title = '<h4>Dart type: $type</h4><h2>$title</h2>';
352 } else {
353 title = '<h2>$title</h2>';
354 }
355 sb.add("""
356 <div class='type' id="$type">
357 <a href='${entry['srcUrl']}'>$title</a>
358 $sbSections
359 $sbExamples
360 $sbMembers
361 </div>
362 """);
363 if (sbExamples.length > 0) {
364 sbAllExamples.add("""
365 <div class='type' id="$type">
366 <a href='${entry['srcUrl']}'>$title</a>
367 $sbExamples
368 </div>
369 """);
370 }
371 }
372
373 for (String type in sortStringCollection(allProps.getKeys())) {
374 if (!matchedTypes.contains(type) &&
375 !database.containsKey(type)) {
376 numSkipped++;
377 sbSkipped.add("""
378 <li class="unknown" id="$type">
379 <a target="_blank" href="http://www.google.com/cse?cx=01719397256594783026 6%3Awpqsk6dy6ee&ie=UTF-8&q=$type">
380 $type
381 </a>
382 </li>
383 """);
384 }
385 }
386
387 sb.add("""
388 <div id="#dart_summary">
389 <h2>Summary</h2>
390 <h3>
391 Generated docs for $numGen classes out of a possible
392 ${allProps.getKeys().length}
393 </h3>
394 <h3>Found documentation for $numFoundMethods methods listed in WebKit</h3>
395 <h3>
396 Found documentation for $numExtraMethods methods not listed in WebKit
397 </h3>
398 <h3>
399 Unable to find documentation for $numMissingMethods methods present in
400 WebKit
401 </h3>
402 <h3>
403 Skipped generating documentation for $numSkipped classes due to no
404 plausible matching files
405 </h3>
406 <ul>
407 $sbSkipped
408 </ul>
409 </div>
410 """);
411 sb.add("""
412 </body>
413 </html>
414 """);
415
416 fs.writeFileSync("output/database.html", sb.toString());
417
418 fs.writeFileSync("output/examples.html", """
419 <html>
420 <head>
421 <style type="text/css">
422 body {
423 background-color: #eee;
424 margin: 10px;
425 font: 14px/1.428 "Lucida Grande", "Lucida Sans Unicode", Lucida, Arial,
426 Helvetica, sans-serif;
427 }
428
429 .debug {
430 color: #888;
431 }
432
433 .example {
434 border: 1px solid #CCC;
435 margin: 5px;
436 padding: 5px;
437 }
438
439 .type {
440 border: 1px solid;
441 margin-top: 10px;
442 margin-bottom: 10px;
443 padding: 10px;
444 overflow: hidden;
445 background-color: white;
446 -moz-box-shadow: 5px 5px 5px #888;
447 -webkit-box-shadow: 5px 5px 5px #888;
448 box-shadow: 5px 5px 5px #888;
449 }
450 </style>
451 <title>All examples</title>
452 </head>
453 <body>
454 <h1>All examples</h1>
455 $sbAllExamples
456 </body>
457 </html>
458 """);
459
460 fs.writeFileSync("output/obsolete.html", """
461 <html>
462 <head>
463 <style type="text/css">
464 body {
465 background-color: #eee;
466 margin: 10px;
467 font: 14px/1.428 "Lucida Grande", "Lucida Sans Unicode", Lucida,
468 Arial, Helvetica, sans-serif;
469 }
470
471 .debug {
472 color: #888;
473 }
474
475 .type {
476 border: 1px solid;
477 margin-top: 10px;
478 margin-bottom: 10px;
479 padding: 10px;
480 overflow: hidden;
481 background-color: white;
482 -moz-box-shadow: 5px 5px 5px #888;
483 -webkit-box-shadow: 5px 5px 5px #888;
484 box-shadow: 5px 5px 5px #888;
485 }
486 </style>
487 <title>Methods marked as obsolete</title>
488 </head>
489 <body>
490 <h1>Methods marked as obsolete</h1>
491 <table>
492 <tbody>
493 <tr>
494 <th>Type</th>
495 <th>Name</th>
496 <th>Description</th>
497 <th>IDL</th>
498 <th>Status</th>
499 </tr>
500 $sbObsolete
501 </tbody>
502 </table>
503 </body>
504 </html>
505 """);
506
507 fs.writeFileSync("output/database.filtered.json", 26 fs.writeFileSync("output/database.filtered.json",
508 JSON.stringify(filteredDb)); 27 JSON.stringify(filteredDb));
28 fs.writeFileSync("output/obsolete.json", JSON.stringify(obsolete));
509 } 29 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698