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

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

Issue 1361163002: remove docgen remnants from repo, update CHANGELOG (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: remove unused code Created 5 years, 2 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
« no previous file with comments | « utils/apidoc/README.txt ('k') | utils/apidoc/docgen.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 /**
6 * This generates the reference documentation for the core libraries that come
7 * with dart. It is built on top of dartdoc, which is a general-purpose library
8 * for generating docs from any Dart code. This library extends that to include
9 * additional information and styling specific to our standard library.
10 *
11 * Usage:
12 *
13 * $ dart apidoc.dart [--out=<output directory>]
14 */
15 library apidoc;
16
17 import 'dart:async';
18 import 'dart:convert';
19 import 'dart:io';
20
21 import 'html_diff.dart';
22
23 import 'package:compiler/src/mirrors/source_mirrors.dart';
24 import 'package:compiler/src/mirrors/mirrors_util.dart';
25 import 'package:compiler/src/filenames.dart';
26 import 'package:dartdoc/dartdoc.dart';
27 import 'package:sdk_library_metadata/libraries.dart';
28 import 'package:path/path.dart' as path;
29
30 HtmlDiff _diff;
31
32 void main(List<String> args) {
33 int mode = MODE_STATIC;
34 String outputDir = 'docs';
35 bool generateAppCache = false;
36
37 List<String> excludedLibraries = <String>[];
38
39 // For libraries that have names matching the package name,
40 // such as library unittest in package unittest, we just give
41 // the package name with a --include-lib argument, such as:
42 // --include-lib=unittest. These arguments are collected in
43 // includedLibraries.
44 List<String> includedLibraries = <String>[];
45
46 // For libraries that lie within packages but have a different name,
47 // such as the matcher library in package unittest, we can use
48 // --extra-lib with a full relative path under pkg, such as
49 // --extra-lib=unittest/lib/matcher.dart. These arguments are
50 // collected in extraLibraries.
51 List<String> extraLibraries = <String>[];
52
53 String packageRoot;
54 String version;
55
56 // Parse the command-line arguments.
57 for (int i = 0; i < args.length; i++) {
58 final arg = args[i];
59
60 switch (arg) {
61 case '--mode=static':
62 mode = MODE_STATIC;
63 break;
64
65 case '--mode=live-nav':
66 mode = MODE_LIVE_NAV;
67 break;
68
69 case '--generate-app-cache=true':
70 generateAppCache = true;
71 break;
72
73 default:
74 if (arg.startsWith('--exclude-lib=')) {
75 excludedLibraries.add(arg.substring('--exclude-lib='.length));
76 } else if (arg.startsWith('--include-lib=')) {
77 includedLibraries.add(arg.substring('--include-lib='.length));
78 } else if (arg.startsWith('--extra-lib=')) {
79 extraLibraries.add(arg.substring('--extra-lib='.length));
80 } else if (arg.startsWith('--out=')) {
81 outputDir = arg.substring('--out='.length);
82 } else if (arg.startsWith('--package-root=')) {
83 packageRoot = arg.substring('--package-root='.length);
84 } else if (arg.startsWith('--version=')) {
85 version = arg.substring('--version='.length);
86 } else {
87 print('Unknown option: $arg');
88 return;
89 }
90 break;
91 }
92 }
93
94 final libPath = path.join(scriptDir, '..', '..', 'sdk/');
95
96 cleanOutputDirectory(outputDir);
97
98 print('Copying static files...');
99 // The basic dartdoc-provided static content.
100 final copiedStatic = copyDirectory(
101 path.join(scriptDir,
102 '..', '..', 'sdk', 'lib', '_internal', 'dartdoc', 'static'),
103 outputDir);
104
105 // The apidoc-specific static content.
106 final copiedApiDocStatic = copyDirectory(
107 path.join(scriptDir, 'static'),
108 outputDir);
109
110 print('Parsing MDN data...');
111 final mdnFile = new File(path.join(scriptDir, 'mdn', 'database.json'));
112 final mdn = JSON.decode(mdnFile.readAsStringSync());
113
114 print('Cross-referencing dart:html...');
115 // TODO(amouravski): move HtmlDiff inside of the future chain below to re-use
116 // the MirrorSystem already analyzed.
117 _diff = new HtmlDiff(printWarnings:false);
118 Future htmlDiff = _diff.run(currentDirectory.resolveUri(path.toUri(libPath)));
119
120 // TODO(johnniwinther): Libraries for the compilation seem to be more like
121 // URIs. Perhaps Path should have a toURI() method.
122 // Add all of the core libraries.
123 final apidocLibraries = <Uri>[];
124 LIBRARIES.forEach((String name, LibraryInfo info) {
125 if (info.documented) {
126 apidocLibraries.add(Uri.parse('dart:$name'));
127 }
128 });
129
130 // TODO(amouravski): This code is really wonky.
131 var lister = new Directory(path.join(scriptDir, '..', '..', 'pkg')).list();
132 lister.listen((entity) {
133 if (entity is Directory) {
134 var libName = path.basename(entity.path);
135 var libPath = path.join(entity.path, 'lib', '${libName}.dart');
136
137 // Ignore some libraries.
138 if (excludedLibraries.contains(libName)) {
139 return;
140 }
141
142 // Ignore hidden directories (like .svn) as well as pkg.xcodeproj.
143 if (libName.startsWith('.') || libName.endsWith('.xcodeproj')) {
144 return;
145 }
146
147 if (new File(libPath).existsSync()) {
148 apidocLibraries.add(path.toUri(libPath));
149 includedLibraries.add(libName);
150 } else {
151 print('Warning: could not find package at ${entity.path}');
152 }
153 }
154 }, onDone: () {
155 // Add any --extra libraries that had full pkg paths.
156 // TODO(gram): if the handling of --include-lib libraries in the
157 // listen() block above is cleaned up, then this will need to be
158 // too, as it is a special case of the above.
159 for (var lib in extraLibraries) {
160 var libPath = '../../$lib';
161 if (new File(libPath).existsSync()) {
162 apidocLibraries.add(path.toUri(libPath));
163 var libName = path.basename(libPath).replaceAll('.dart', '');
164 includedLibraries.add(libName);
165 }
166 }
167
168 final apidoc = new Apidoc(mdn, outputDir, mode, generateAppCache,
169 excludedLibraries, version);
170 apidoc.dartdocPath =
171 path.join(scriptDir, '..', '..', 'sdk', 'lib', '_internal', 'dartdoc');
172 // Select the libraries to include in the produced documentation:
173 apidoc.includeApi = true;
174 apidoc.includedLibraries = includedLibraries;
175
176 // TODO(amouravski): make apidoc use roughly the same flow as bin/dartdoc.
177 Future.wait([copiedStatic, copiedApiDocStatic, htmlDiff])
178 .then((_) => apidoc.documentLibraries(apidocLibraries, libPath,
179 packageRoot))
180 .then((_) => compileScript(mode, outputDir, libPath, apidoc.tmpPath))
181 .then((_) => print(apidoc.status))
182 .catchError((e, trace) {
183 print('Error: generation failed: ${e}');
184 if (trace != null) print("StackTrace: $trace");
185 apidoc.cleanup();
186 exit(1);
187 })
188 .whenComplete(() => apidoc.cleanup());
189 });
190 }
191
192 class Apidoc extends Dartdoc {
193 /** Big ball of JSON containing the scraped MDN documentation. */
194 final Map mdn;
195
196
197 // A set of type names (TypeMirror.simpleName values) to ignore while
198 // looking up information from MDN data. TODO(eub, jacobr): fix up the MDN
199 // import scripts so they run correctly and generate data that doesn't have
200 // any entries that need to be ignored.
201 static Set<String> _mdnTypeNamesToSkip = null;
202
203 /**
204 * The URL to the page on MDN that content was pulled from for the current
205 * type being documented. Will be `null` if the type doesn't use any MDN
206 * content.
207 */
208 String mdnUrl = null;
209
210 Apidoc(this.mdn, String outputDir, int mode, bool generateAppCache,
211 [List<String> excludedLibraries, String version]) {
212 if (excludedLibraries != null) this.excludedLibraries = excludedLibraries;
213 this.version = version;
214 this.outputDir = outputDir;
215 this.mode = mode;
216 this.generateAppCache = generateAppCache;
217
218 // Skip bad entries in the checked-in mdn/database.json:
219 // * UnknownElement has a top-level Gecko DOM page in German.
220 if (_mdnTypeNamesToSkip == null)
221 _mdnTypeNamesToSkip = new Set.from(['UnknownElement']);
222
223 mainTitle = 'Dart API Reference';
224 mainUrl = 'http://dartlang.org';
225
226 final note = 'http://code.google.com/policies.html#restrictions';
227 final cca = 'http://creativecommons.org/licenses/by/3.0/';
228 final bsd = 'http://code.google.com/google_bsd_license.html';
229 final tos = 'http://www.dartlang.org/tos.html';
230 final privacy = 'http://www.google.com/intl/en/privacy/privacy-policy.html';
231
232 footerText =
233 '''
234 <p>Except as otherwise <a href="$note">noted</a>, the content of this
235 page is licensed under the <a href="$cca">Creative Commons Attribution
236 3.0 License</a>, and code samples are licensed under the
237 <a href="$bsd">BSD License</a>.</p>
238 <p><a href="$tos">Terms of Service</a> |
239 <a href="$privacy">Privacy Policy</a></p>
240 ''';
241
242 searchEngineId = '011220921317074318178:i4mscbaxtru';
243 searchResultsUrl = 'http://www.dartlang.org/search.html';
244 }
245
246 void writeHeadContents(String title) {
247 super.writeHeadContents(title);
248
249 // Include the apidoc-specific CSS.
250 // TODO(rnystrom): Use our CSS pre-processor to combine these.
251 writeln(
252 '''
253 <link rel="stylesheet" type="text/css"
254 href="${relativePath('apidoc-styles.css')}" />
255 ''');
256
257 // Add the analytics code.
258 writeln(
259 '''
260 <script type="text/javascript">
261 var _gaq = _gaq || [];
262 _gaq.push(["_setAccount", "UA-26406144-9"]);
263 _gaq.push(["_trackPageview"]);
264
265 (function() {
266 var ga = document.createElement("script");
267 ga.type = "text/javascript"; ga.async = true;
268 ga.src = ("https:" == document.location.protocol ?
269 "https://ssl" : "http://www") + ".google-analytics.com/ga.js";
270 var s = document.getElementsByTagName("script")[0];
271 s.parentNode.insertBefore(ga, s);
272 })();
273 </script>
274 ''');
275 }
276
277 void docIndexLibrary(LibraryMirror library) {
278 // TODO(rnystrom): Hackish. The IO libraries reference this but we don't
279 // want it in the docs.
280 if (displayName(library) == 'dart:nativewrappers') return;
281 super.docIndexLibrary(library);
282 }
283
284 void docLibraryNavigationJson(LibraryMirror library, List libraryList) {
285 // TODO(rnystrom): Hackish. The IO libraries reference this but we don't
286 // want it in the docs.
287 if (displayName(library) == 'dart:nativewrappers') return;
288 super.docLibraryNavigationJson(library, libraryList);
289 }
290
291 void docLibrary(LibraryMirror library) {
292 // TODO(rnystrom): Hackish. The IO libraries reference this but we don't
293 // want it in the docs.
294 if (displayName(library) == 'dart:nativewrappers') return;
295 super.docLibrary(library);
296 }
297
298 DocComment getLibraryComment(LibraryMirror library) {
299 return super.getLibraryComment(library);
300 }
301
302 DocComment getTypeComment(TypeMirror type) {
303 return _mergeDocs(
304 includeMdnTypeComment(type), super.getTypeComment(type));
305 }
306
307 DocComment getMemberComment(DeclarationMirror member) {
308 return _mergeDocs(
309 includeMdnMemberComment(member), super.getMemberComment(member));
310 }
311
312 DocComment _mergeDocs(MdnComment mdnComment,
313 DocComment fileComment) {
314 // Otherwise, prefer comment from the (possibly generated) Dart file.
315 if (fileComment != null) return fileComment;
316
317 // Finally, fallback on MDN if available.
318 if (mdnComment != null) {
319 mdnUrl = mdnComment.mdnUrl;
320 return mdnComment;
321 }
322
323 // We got nothing!
324 return null;
325 }
326
327 void docType(TypeMirror type) {
328 // Track whether we've inserted MDN content into this page.
329 mdnUrl = null;
330
331 super.docType(type);
332 }
333
334 void writeTypeFooter() {
335 if (mdnUrl != null) {
336 final MOZ = 'http://www.mozilla.org/';
337 final MDN = 'https://developer.mozilla.org';
338 final CCA = 'http://creativecommons.org/licenses/by-sa/2.5/';
339 final CONTRIB = 'https://developer.mozilla.org/Project:en/How_to_Help';
340 writeln(
341 '''
342 <p class="mdn-attribution">
343 <a href="$MDN">
344 <img src="${relativePath('mdn-logo-tiny.png')}" class="mdn-logo" />
345 </a>
346 This page includes <a href="$mdnUrl">content</a> from the
347 <a href="$MOZ">Mozilla Foundation</a> that is graciously
348 <a href="$MDN/Project:Copyrights">licensed</a> under a
349 <a href="$CCA">Creative Commons: Attribution-Sharealike license</a>.
350 Mozilla has no other association with Dart or dartlang.org. We
351 encourage you to improve the web by
352 <a href="$CONTRIB">contributing</a> to
353 <a href="$MDN">The Mozilla Developer Network</a>.
354 </p>
355 ''');
356 }
357 }
358
359 MdnComment lookupMdnComment(Mirror mirror) {
360 if (mirror is TypeMirror) {
361 return includeMdnTypeComment(mirror);
362 } else if (mirror is MethodMirror || mirror is VariableMirror) {
363 return includeMdnMemberComment(mirror);
364 } else {
365 return null;
366 }
367 }
368
369 /**
370 * Gets the MDN-scraped docs for [type], or `null` if this type isn't
371 * scraped from MDN.
372 */
373 MdnComment includeMdnTypeComment(TypeMirror type) {
374 if (_mdnTypeNamesToSkip.contains(type.simpleName)) {
375 return null;
376 }
377
378 var typeString = '';
379 if (HTML_LIBRARY_URIS.contains(getLibrary(type).uri)) {
380 // If it's an HTML type, try to map it to a base DOM type so we can find
381 // the MDN docs.
382 final domTypes = _diff.htmlTypesToDom[type.qualifiedName];
383
384 // Couldn't find a DOM type.
385 if ((domTypes == null) || (domTypes.length != 1)) return null;
386
387 // Use the corresponding DOM type when searching MDN.
388 // TODO(rnystrom): Shame there isn't a simpler way to get the one item
389 // out of a singleton Set.
390 // TODO(floitsch): switch to domTypes.first, once that's implemented.
391 var iter = domTypes.iterator;
392 iter.moveNext();
393 typeString = iter.current;
394 } else {
395 // Not a DOM type.
396 return null;
397 }
398
399 final mdnType = mdn[typeString];
400 if (mdnType == null) return null;
401 if (mdnType['skipped'] != null) return null;
402 if (mdnType['summary'] == null) return null;
403 if (mdnType['summary'].trim().isEmpty) return null;
404
405 // Remember which MDN page we're using so we can attribute it.
406 return new MdnComment(mdnType['summary'], mdnType['srcUrl']);
407 }
408
409 /**
410 * Gets the MDN-scraped docs for [member], or `null` if this type isn't
411 * scraped from MDN.
412 */
413 MdnComment includeMdnMemberComment(DeclarationMirror member) {
414 var library = getLibrary(member);
415 var memberString = '';
416 if (HTML_LIBRARY_URIS.contains(library.uri)) {
417 // If it's an HTML type, try to map it to a DOM type name so we can find
418 // the MDN docs.
419 final domMembers = _diff.htmlToDom[member.qualifiedName];
420
421 // Couldn't find a DOM type.
422 if ((domMembers == null) || (domMembers.length != 1)) return null;
423
424 // Use the corresponding DOM member when searching MDN.
425 // TODO(rnystrom): Shame there isn't a simpler way to get the one item
426 // out of a singleton Set.
427 // TODO(floitsch): switch to domTypes.first, once that's implemented.
428 var iter = domMembers.iterator;
429 iter.moveNext();
430 memberString = iter.current;
431 } else {
432 // Not a DOM type.
433 return null;
434 }
435
436 // Ignore top-level functions.
437 if (member.isTopLevel) return null;
438
439 var mdnMember = null;
440 var mdnType = null;
441 var pieces = memberString.split('.');
442 if (pieces.length == 2) {
443 mdnType = mdn[pieces[0]];
444 if (mdnType == null) return null;
445 var nameToFind = pieces[1];
446 for (final candidateMember in mdnType['members']) {
447 if (candidateMember['name'] == nameToFind) {
448 mdnMember = candidateMember;
449 break;
450 }
451 }
452 }
453
454 if (mdnMember == null) return null;
455 if (mdnMember['help'] == null) return null;
456 if (mdnMember['help'].trim().isEmpty) return null;
457
458 // Remember which MDN page we're using so we can attribute it.
459 return new MdnComment(mdnMember['help'], mdnType['srcUrl']);
460 }
461
462 /**
463 * Returns a link to [member], relative to a type page that may be in a
464 * different library than [member].
465 */
466 String _linkMember(DeclarationMirror member) {
467 final typeName = member.owner.simpleName;
468 var memberName = '$typeName.${member.simpleName}';
469 if (member is MethodMirror && member.isConstructor) {
470 final separator = member.constructorName == '' ? '' : '.';
471 memberName = 'new $typeName$separator${member.constructorName}';
472 }
473
474 return a(memberUrl(member), memberName);
475 }
476 }
477
OLDNEW
« no previous file with comments | « utils/apidoc/README.txt ('k') | utils/apidoc/docgen.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698