OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * This generates the reference documentation for the core libraries that come | 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 | 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 | 8 * for generating docs from any Dart code. This library extends that to include |
9 * additional information and styling specific to our standard library. | 9 * additional information and styling specific to our standard library. |
10 * | 10 * |
11 * Usage: | 11 * Usage: |
12 * | 12 * |
13 * $ dart apidoc.dart [--out=<output directory>] | 13 * $ dart apidoc.dart [--out=<output directory>] |
14 */ | 14 */ |
15 library apidoc; | 15 library apidoc; |
16 | 16 |
17 import 'dart:async'; | 17 import 'dart:async'; |
18 import 'dart:io'; | 18 import 'dart:io'; |
19 import 'dart:json' as json; | 19 import 'dart:json' as json; |
| 20 |
20 import 'html_diff.dart'; | 21 import 'html_diff.dart'; |
| 22 |
21 // TODO(rnystrom): Use "package:" URL (#4968). | 23 // TODO(rnystrom): Use "package:" URL (#4968). |
22 import '../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart'; | 24 import '../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart'; |
23 import '../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util.dar
t'; | 25 import '../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util.dar
t'; |
24 import '../../sdk/lib/_internal/dartdoc/lib/dartdoc.dart' as doc; | 26 import '../../sdk/lib/_internal/dartdoc/lib/dartdoc.dart'; |
25 import '../../sdk/lib/_internal/libraries.dart'; | 27 import '../../sdk/lib/_internal/libraries.dart'; |
26 | 28 |
27 HtmlDiff _diff; | 29 HtmlDiff _diff; |
28 | 30 |
29 void main() { | 31 void main() { |
30 final args = new Options().arguments; | 32 final args = new Options().arguments; |
31 | 33 |
32 int mode = doc.MODE_STATIC; | 34 int mode = MODE_STATIC; |
33 Path outputDir = new Path('docs'); | 35 Path outputDir = new Path('docs'); |
34 bool generateAppCache = false; | 36 bool generateAppCache = false; |
35 | 37 |
36 List<String> excludedLibraries = <String>[]; | 38 List<String> excludedLibraries = <String>[]; |
37 List<String> includedLibraries = <String>[]; | 39 List<String> includedLibraries = <String>[]; |
38 Path pkgPath; | 40 Path pkgPath; |
39 String version; | 41 String version; |
40 | 42 |
41 // Parse the command-line arguments. | 43 // Parse the command-line arguments. |
42 for (int i = 0; i < args.length; i++) { | 44 for (int i = 0; i < args.length; i++) { |
43 final arg = args[i]; | 45 final arg = args[i]; |
44 | 46 |
45 switch (arg) { | 47 switch (arg) { |
46 case '--mode=static': | 48 case '--mode=static': |
47 mode = doc.MODE_STATIC; | 49 mode = MODE_STATIC; |
48 break; | 50 break; |
49 | 51 |
50 case '--mode=live-nav': | 52 case '--mode=live-nav': |
51 mode = doc.MODE_LIVE_NAV; | 53 mode = MODE_LIVE_NAV; |
52 break; | 54 break; |
53 | 55 |
54 case '--generate-app-cache=true': | 56 case '--generate-app-cache=true': |
55 generateAppCache = true; | 57 generateAppCache = true; |
56 break; | 58 break; |
57 | 59 |
58 default: | 60 default: |
59 if (arg.startsWith('--exclude-lib=')) { | 61 if (arg.startsWith('--exclude-lib=')) { |
60 excludedLibraries.add(arg.substring('--exclude-lib='.length)); | 62 excludedLibraries.add(arg.substring('--exclude-lib='.length)); |
61 } else if (arg.startsWith('--include-lib=')) { | 63 } else if (arg.startsWith('--include-lib=')) { |
62 includedLibraries.add(arg.substring('--include-lib='.length)); | 64 includedLibraries.add(arg.substring('--include-lib='.length)); |
63 } else if (arg.startsWith('--out=')) { | 65 } else if (arg.startsWith('--out=')) { |
64 outputDir = new Path(arg.substring('--out='.length)); | 66 outputDir = new Path(arg.substring('--out='.length)); |
65 } else if (arg.startsWith('--pkg=')) { | 67 } else if (arg.startsWith('--pkg=')) { |
66 pkgPath = new Path(arg.substring('--pkg='.length)); | 68 pkgPath = new Path(arg.substring('--pkg='.length)); |
67 } else if (arg.startsWith('--version=')) { | 69 } else if (arg.startsWith('--version=')) { |
68 version = arg.substring('--version='.length); | 70 version = arg.substring('--version='.length); |
69 } else { | 71 } else { |
70 print('Unknown option: $arg'); | 72 print('Unknown option: $arg'); |
71 return; | 73 return; |
72 } | 74 } |
73 break; | 75 break; |
74 } | 76 } |
75 } | 77 } |
76 | 78 |
77 final libPath = doc.scriptDir.append('../../sdk/'); | 79 final libPath = scriptDir.append('../../sdk/'); |
78 | 80 |
79 doc.cleanOutputDirectory(outputDir); | 81 cleanOutputDirectory(outputDir); |
80 | 82 |
| 83 print('Copying static files...'); |
81 // The basic dartdoc-provided static content. | 84 // The basic dartdoc-provided static content. |
82 final copiedStatic = doc.copyDirectory( | 85 final copiedStatic = copyDirectory( |
83 doc.scriptDir.append('../../sdk/lib/_internal/dartdoc/static'), | 86 scriptDir.append('../../sdk/lib/_internal/dartdoc/static'), |
84 outputDir); | 87 outputDir); |
85 | 88 |
86 // The apidoc-specific static content. | 89 // The apidoc-specific static content. |
87 final copiedApiDocStatic = doc.copyDirectory( | 90 final copiedApiDocStatic = copyDirectory( |
88 doc.scriptDir.append('static'), | 91 scriptDir.append('static'), |
89 outputDir); | 92 outputDir); |
90 | 93 |
91 print('Parsing MDN data...'); | 94 print('Parsing MDN data...'); |
92 final mdnFile = new File.fromPath(doc.scriptDir.append('mdn/database.json')); | 95 final mdnFile = new File.fromPath(scriptDir.append('mdn/database.json')); |
93 final mdn = json.parse(mdnFile.readAsStringSync()); | 96 final mdn = json.parse(mdnFile.readAsStringSync()); |
94 | 97 |
95 print('Cross-referencing dart:html...'); | 98 print('Cross-referencing dart:html...'); |
| 99 // TODO(amouravski): move HtmlDiff inside of the future chain below to re-use |
| 100 // the MirrorSystem already analyzed. |
96 _diff = new HtmlDiff(printWarnings:false); | 101 _diff = new HtmlDiff(printWarnings:false); |
97 Future htmlDiff = _diff.run(libPath); | 102 Future htmlDiff = _diff.run(libPath); |
98 | 103 |
99 // Process libraries. | |
100 | |
101 // TODO(johnniwinther): Libraries for the compilation seem to be more like | 104 // TODO(johnniwinther): Libraries for the compilation seem to be more like |
102 // URIs. Perhaps Path should have a toURI() method. | 105 // URIs. Perhaps Path should have a toURI() method. |
103 // Add all of the core libraries. | 106 // Add all of the core libraries. |
104 final apidocLibraries = <Path>[]; | 107 final apidocLibraries = <Path>[]; |
105 LIBRARIES.forEach((String name, LibraryInfo info) { | 108 LIBRARIES.forEach((String name, LibraryInfo info) { |
106 if (info.documented) { | 109 if (info.documented) { |
107 apidocLibraries.add(new Path('dart:$name')); | 110 apidocLibraries.add(new Path('dart:$name')); |
108 } | 111 } |
109 }); | 112 }); |
110 | 113 |
111 var lister = new Directory.fromPath(doc.scriptDir.append('../../pkg')).list(); | 114 // TODO(amouravski): This code is really wonky. |
112 lister.listen( | 115 var lister = new Directory.fromPath(scriptDir.append('../../pkg')).list(); |
113 (entity) { | 116 lister.listen((entity) { |
114 if (entity is Directory) { | 117 if (entity is Directory) { |
115 var path = new Path(entity.path); | 118 var path = new Path(entity.path); |
116 var libName = path.filename; | 119 var libName = path.filename; |
| 120 var libPath = path.append('lib/$libName.dart'); |
117 | 121 |
118 // Ignore hidden directories (like .svn) as well as pkg.xcodeproj. | 122 // Ignore some libraries. |
119 if (libName.startsWith('.') || libName.endsWith('.xcodeproj')) { | 123 if (excludedLibraries.contains(libName)) { |
120 return; | 124 return; |
121 } | 125 } |
122 | 126 |
123 // TODO(rnystrom): Get rid of oldStylePath support when all | 127 // Ignore hidden directories (like .svn) as well as pkg.xcodeproj. |
124 // packages are using new layout. See #5106. | 128 if (libName.startsWith('.') || libName.endsWith('.xcodeproj')) { |
125 var oldStylePath = path.append('${libName}.dart'); | 129 return; |
126 var newStylePath = path.append('lib/${libName}.dart'); | 130 } |
127 | 131 |
128 if (new File.fromPath(oldStylePath).existsSync()) { | 132 if (new File.fromPath(libPath).existsSync()) { |
129 apidocLibraries.add(oldStylePath); | 133 apidocLibraries.add(libPath); |
130 includedLibraries.add(libName); | 134 includedLibraries.add(libName); |
131 } else if (new File.fromPath(newStylePath).existsSync()) { | 135 } else { |
132 apidocLibraries.add(newStylePath); | 136 print('Warning: could not find package at $path'); |
133 includedLibraries.add(libName); | 137 } |
134 } else { | 138 } |
135 print('Warning: could not find package at $path'); | 139 }, onDone: () { |
136 } | 140 final apidoc = new Apidoc(mdn, outputDir, mode, generateAppCache, |
137 } | 141 excludedLibraries, version); |
138 }, | 142 apidoc.dartdocPath = |
139 onDone: () { | 143 scriptDir.append('../../sdk/lib/_internal/dartdoc/'); |
140 print('Generating docs...'); | 144 // Select the libraries to include in the produced documentation: |
141 final apidoc = new Apidoc(mdn, outputDir, mode, generateAppCache, | 145 apidoc.includeApi = true; |
142 excludedLibraries, version); | 146 apidoc.includedLibraries = includedLibraries; |
143 apidoc.dartdocPath = | |
144 doc.scriptDir.append('../../sdk/lib/_internal/dartdoc/'); | |
145 // Select the libraries to include in the produced documentation: | |
146 apidoc.includeApi = true; | |
147 apidoc.includedLibraries = includedLibraries; | |
148 | 147 |
149 Future.wait([copiedStatic, copiedApiDocStatic, htmlDiff]).then((_) { | 148 // TODO(amouravski): make apidoc use roughly the same flow as bin/dartdoc. |
150 Future<bool> documented = | 149 Future.wait([copiedStatic, copiedApiDocStatic, htmlDiff]) |
151 apidoc.documentLibraries(apidocLibraries, libPath, pkgPath); | 150 .then((_) => apidoc.documentLibraries(apidocLibraries, libPath, pkgPath)) |
152 | 151 .then((_) => compileScript(mode, outputDir, libPath)) |
153 documented.then((_) { | 152 .then((_) => print(apidoc.status)) |
154 final compiled = doc.compileScript(mode, outputDir, libPath); | 153 .catchError((e) => print('Error: generation failed: ${e.error}')) |
155 | 154 .whenComplete(() => apidoc.cleanup()); |
156 Future.wait([compiled]).then((_) { | 155 }); |
157 apidoc.cleanup(); | |
158 }); | |
159 }, onError: (AsyncError asyncError) { | |
160 print('Generation failed: ${asyncError.error}'); | |
161 apidoc.cleanup(); | |
162 }); | |
163 }); | |
164 }); | |
165 } | 156 } |
166 | 157 |
167 class Apidoc extends doc.Dartdoc { | 158 class Apidoc extends Dartdoc { |
168 /** Big ball of JSON containing the scraped MDN documentation. */ | 159 /** Big ball of JSON containing the scraped MDN documentation. */ |
169 final Map mdn; | 160 final Map mdn; |
170 | 161 |
171 | 162 |
172 // A set of type names (TypeMirror.simpleName values) to ignore while | 163 // A set of type names (TypeMirror.simpleName values) to ignore while |
173 // looking up information from MDN data. TODO(eub, jacobr): fix up the MDN | 164 // looking up information from MDN data. TODO(eub, jacobr): fix up the MDN |
174 // import scripts so they run correctly and generate data that doesn't have | 165 // import scripts so they run correctly and generate data that doesn't have |
175 // any entries that need to be ignored. | 166 // any entries that need to be ignored. |
176 static Set<String> _mdnTypeNamesToSkip = null; | 167 static Set<String> _mdnTypeNamesToSkip = null; |
177 | 168 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 var s = document.getElementsByTagName("script")[0]; | 238 var s = document.getElementsByTagName("script")[0]; |
248 s.parentNode.insertBefore(ga, s); | 239 s.parentNode.insertBefore(ga, s); |
249 })(); | 240 })(); |
250 </script> | 241 </script> |
251 '''); | 242 '''); |
252 } | 243 } |
253 | 244 |
254 void docIndexLibrary(LibraryMirror library) { | 245 void docIndexLibrary(LibraryMirror library) { |
255 // TODO(rnystrom): Hackish. The IO libraries reference this but we don't | 246 // TODO(rnystrom): Hackish. The IO libraries reference this but we don't |
256 // want it in the docs. | 247 // want it in the docs. |
257 if (doc.displayName(library) == 'dart:nativewrappers') return; | 248 if (displayName(library) == 'dart:nativewrappers') return; |
258 super.docIndexLibrary(library); | 249 super.docIndexLibrary(library); |
259 } | 250 } |
260 | 251 |
261 void docLibraryNavigationJson(LibraryMirror library, List libraryList) { | 252 void docLibraryNavigationJson(LibraryMirror library, List libraryList) { |
262 // TODO(rnystrom): Hackish. The IO libraries reference this but we don't | 253 // TODO(rnystrom): Hackish. The IO libraries reference this but we don't |
263 // want it in the docs. | 254 // want it in the docs. |
264 if (doc.displayName(library) == 'dart:nativewrappers') return; | 255 if (displayName(library) == 'dart:nativewrappers') return; |
265 super.docLibraryNavigationJson(library, libraryList); | 256 super.docLibraryNavigationJson(library, libraryList); |
266 } | 257 } |
267 | 258 |
268 void docLibrary(LibraryMirror library) { | 259 void docLibrary(LibraryMirror library) { |
269 // TODO(rnystrom): Hackish. The IO libraries reference this but we don't | 260 // TODO(rnystrom): Hackish. The IO libraries reference this but we don't |
270 // want it in the docs. | 261 // want it in the docs. |
271 if (doc.displayName(library) == 'dart:nativewrappers') return; | 262 if (displayName(library) == 'dart:nativewrappers') return; |
272 super.docLibrary(library); | 263 super.docLibrary(library); |
273 } | 264 } |
274 | 265 |
275 doc.DocComment getLibraryComment(LibraryMirror library) { | 266 DocComment getLibraryComment(LibraryMirror library) { |
276 return super.getLibraryComment(library); | 267 return super.getLibraryComment(library); |
277 } | 268 } |
278 | 269 |
279 doc.DocComment getTypeComment(TypeMirror type) { | 270 DocComment getTypeComment(TypeMirror type) { |
280 return _mergeDocs( | 271 return _mergeDocs( |
281 includeMdnTypeComment(type), super.getTypeComment(type)); | 272 includeMdnTypeComment(type), super.getTypeComment(type)); |
282 } | 273 } |
283 | 274 |
284 doc.DocComment getMemberComment(MemberMirror member) { | 275 DocComment getMemberComment(MemberMirror member) { |
285 return _mergeDocs( | 276 return _mergeDocs( |
286 includeMdnMemberComment(member), super.getMemberComment(member)); | 277 includeMdnMemberComment(member), super.getMemberComment(member)); |
287 } | 278 } |
288 | 279 |
289 doc.DocComment _mergeDocs(doc.MdnComment mdnComment, | 280 DocComment _mergeDocs(MdnComment mdnComment, |
290 doc.DocComment fileComment) { | 281 DocComment fileComment) { |
291 // Otherwise, prefer comment from the (possibly generated) Dart file. | 282 // Otherwise, prefer comment from the (possibly generated) Dart file. |
292 if (fileComment != null) return fileComment; | 283 if (fileComment != null) return fileComment; |
293 | 284 |
294 // Finally, fallback on MDN if available. | 285 // Finally, fallback on MDN if available. |
295 if (mdnComment != null) { | 286 if (mdnComment != null) { |
296 mdnUrl = mdnComment.mdnUrl; | 287 mdnUrl = mdnComment.mdnUrl; |
297 return mdnComment; | 288 return mdnComment; |
298 } | 289 } |
299 | 290 |
300 // We got nothing! | 291 // We got nothing! |
(...skipping 25 matching lines...) Expand all Loading... |
326 <a href="$CCA">Creative Commons: Attribution-Sharealike license</a>. | 317 <a href="$CCA">Creative Commons: Attribution-Sharealike license</a>. |
327 Mozilla has no other association with Dart or dartlang.org. We | 318 Mozilla has no other association with Dart or dartlang.org. We |
328 encourage you to improve the web by | 319 encourage you to improve the web by |
329 <a href="$CONTRIB">contributing</a> to | 320 <a href="$CONTRIB">contributing</a> to |
330 <a href="$MDN">The Mozilla Developer Network</a>. | 321 <a href="$MDN">The Mozilla Developer Network</a>. |
331 </p> | 322 </p> |
332 '''); | 323 '''); |
333 } | 324 } |
334 } | 325 } |
335 | 326 |
336 doc.MdnComment lookupMdnComment(Mirror mirror) { | 327 MdnComment lookupMdnComment(Mirror mirror) { |
337 if (mirror is TypeMirror) { | 328 if (mirror is TypeMirror) { |
338 return includeMdnTypeComment(mirror); | 329 return includeMdnTypeComment(mirror); |
339 } else if (mirror is MemberMirror) { | 330 } else if (mirror is MemberMirror) { |
340 return includeMdnMemberComment(mirror); | 331 return includeMdnMemberComment(mirror); |
341 } else { | 332 } else { |
342 return null; | 333 return null; |
343 } | 334 } |
344 } | 335 } |
345 | 336 |
346 /** | 337 /** |
347 * Gets the MDN-scraped docs for [type], or `null` if this type isn't | 338 * Gets the MDN-scraped docs for [type], or `null` if this type isn't |
348 * scraped from MDN. | 339 * scraped from MDN. |
349 */ | 340 */ |
350 doc.MdnComment includeMdnTypeComment(TypeMirror type) { | 341 MdnComment includeMdnTypeComment(TypeMirror type) { |
351 if (_mdnTypeNamesToSkip.contains(type.simpleName)) { | 342 if (_mdnTypeNamesToSkip.contains(type.simpleName)) { |
352 print('Skipping MDN type ${type.simpleName}'); | |
353 return null; | 343 return null; |
354 } | 344 } |
355 | 345 |
356 var typeString = ''; | 346 var typeString = ''; |
357 if (HTML_LIBRARY_NAMES.contains(doc.displayName(type.library))) { | 347 if (HTML_LIBRARY_NAMES.contains(displayName(type.library))) { |
358 // If it's an HTML type, try to map it to a base DOM type so we can find | 348 // If it's an HTML type, try to map it to a base DOM type so we can find |
359 // the MDN docs. | 349 // the MDN docs. |
360 final domTypes = _diff.htmlTypesToDom[type.qualifiedName]; | 350 final domTypes = _diff.htmlTypesToDom[type.qualifiedName]; |
361 | 351 |
362 // Couldn't find a DOM type. | 352 // Couldn't find a DOM type. |
363 if ((domTypes == null) || (domTypes.length != 1)) return null; | 353 if ((domTypes == null) || (domTypes.length != 1)) return null; |
364 | 354 |
365 // Use the corresponding DOM type when searching MDN. | 355 // Use the corresponding DOM type when searching MDN. |
366 // TODO(rnystrom): Shame there isn't a simpler way to get the one item | 356 // TODO(rnystrom): Shame there isn't a simpler way to get the one item |
367 // out of a singleton Set. | 357 // out of a singleton Set. |
368 // TODO(floitsch): switch to domTypes.first, once that's implemented. | 358 // TODO(floitsch): switch to domTypes.first, once that's implemented. |
369 var iter = domTypes.iterator; | 359 var iter = domTypes.iterator; |
370 iter.moveNext(); | 360 iter.moveNext(); |
371 typeString = iter.current; | 361 typeString = iter.current; |
372 } else { | 362 } else { |
373 // Not a DOM type. | 363 // Not a DOM type. |
374 return null; | 364 return null; |
375 } | 365 } |
376 | 366 |
377 final mdnType = mdn[typeString]; | 367 final mdnType = mdn[typeString]; |
378 if (mdnType == null) return null; | 368 if (mdnType == null) return null; |
379 if (mdnType['skipped'] != null) return null; | 369 if (mdnType['skipped'] != null) return null; |
380 if (mdnType['summary'] == null) return null; | 370 if (mdnType['summary'] == null) return null; |
381 if (mdnType['summary'].trim().isEmpty) return null; | 371 if (mdnType['summary'].trim().isEmpty) return null; |
382 | 372 |
383 // Remember which MDN page we're using so we can attribute it. | 373 // Remember which MDN page we're using so we can attribute it. |
384 return new doc.MdnComment(mdnType['summary'], mdnType['srcUrl']); | 374 return new MdnComment(mdnType['summary'], mdnType['srcUrl']); |
385 } | 375 } |
386 | 376 |
387 /** | 377 /** |
388 * Gets the MDN-scraped docs for [member], or `null` if this type isn't | 378 * Gets the MDN-scraped docs for [member], or `null` if this type isn't |
389 * scraped from MDN. | 379 * scraped from MDN. |
390 */ | 380 */ |
391 doc.MdnComment includeMdnMemberComment(MemberMirror member) { | 381 MdnComment includeMdnMemberComment(MemberMirror member) { |
392 var library = findLibrary(member); | 382 var library = findLibrary(member); |
393 var memberString = ''; | 383 var memberString = ''; |
394 if (HTML_LIBRARY_NAMES.contains(doc.displayName(library))) { | 384 if (HTML_LIBRARY_NAMES.contains(displayName(library))) { |
395 // If it's an HTML type, try to map it to a DOM type name so we can find | 385 // If it's an HTML type, try to map it to a DOM type name so we can find |
396 // the MDN docs. | 386 // the MDN docs. |
397 final domMembers = _diff.htmlToDom[member.qualifiedName]; | 387 final domMembers = _diff.htmlToDom[member.qualifiedName]; |
398 | 388 |
399 // Couldn't find a DOM type. | 389 // Couldn't find a DOM type. |
400 if ((domMembers == null) || (domMembers.length != 1)) return null; | 390 if ((domMembers == null) || (domMembers.length != 1)) return null; |
401 | 391 |
402 // Use the corresponding DOM member when searching MDN. | 392 // Use the corresponding DOM member when searching MDN. |
403 // TODO(rnystrom): Shame there isn't a simpler way to get the one item | 393 // TODO(rnystrom): Shame there isn't a simpler way to get the one item |
404 // out of a singleton Set. | 394 // out of a singleton Set. |
(...skipping 22 matching lines...) Expand all Loading... |
427 break; | 417 break; |
428 } | 418 } |
429 } | 419 } |
430 } | 420 } |
431 | 421 |
432 if (mdnMember == null) return null; | 422 if (mdnMember == null) return null; |
433 if (mdnMember['help'] == null) return null; | 423 if (mdnMember['help'] == null) return null; |
434 if (mdnMember['help'].trim().isEmpty) return null; | 424 if (mdnMember['help'].trim().isEmpty) return null; |
435 | 425 |
436 // Remember which MDN page we're using so we can attribute it. | 426 // Remember which MDN page we're using so we can attribute it. |
437 return new doc.MdnComment(mdnMember['help'], mdnType['srcUrl']); | 427 return new MdnComment(mdnMember['help'], mdnType['srcUrl']); |
438 } | 428 } |
439 | 429 |
440 /** | 430 /** |
441 * Returns a link to [member], relative to a type page that may be in a | 431 * Returns a link to [member], relative to a type page that may be in a |
442 * different library than [member]. | 432 * different library than [member]. |
443 */ | 433 */ |
444 String _linkMember(MemberMirror member) { | 434 String _linkMember(MemberMirror member) { |
445 final typeName = member.owner.simpleName; | 435 final typeName = member.owner.simpleName; |
446 var memberName = '$typeName.${member.simpleName}'; | 436 var memberName = '$typeName.${member.simpleName}'; |
447 if (member is MethodMirror && (member.isConstructor || member.isFactory)) { | 437 if (member is MethodMirror && (member.isConstructor || member.isFactory)) { |
448 final separator = member.constructorName == '' ? '' : '.'; | 438 final separator = member.constructorName == '' ? '' : '.'; |
449 memberName = 'new $typeName$separator${member.constructorName}'; | 439 memberName = 'new $typeName$separator${member.constructorName}'; |
450 } | 440 } |
451 | 441 |
452 return a(memberUrl(member), memberName); | 442 return a(memberUrl(member), memberName); |
453 } | 443 } |
454 } | 444 } |
OLD | NEW |