OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 * **docgen** is a tool for creating machine readable representations of Dart | 6 * **docgen** is a tool for creating machine readable representations of Dart |
7 * code metadata, including: classes, members, comments and annotations. | 7 * code metadata, including: classes, members, comments and annotations. |
8 * | 8 * |
9 * docgen is run on a `.dart` file or a directory containing `.dart` files. | 9 * docgen is run on a `.dart` file or a directory containing `.dart` files. |
10 * | 10 * |
11 * $ dart docgen.dart [OPTIONS] [FILE/DIR] | 11 * $ dart docgen.dart [OPTIONS] [FILE/DIR] |
12 * | 12 * |
13 * This creates files called `docs/<library_name>.yaml` in your current | 13 * This creates files called `docs/<library_name>.yaml` in your current |
14 * working directory. | 14 * working directory. |
15 */ | 15 */ |
16 library docgen; | 16 library docgen; |
17 | 17 |
18 import 'dart:io'; | 18 import 'dart:io'; |
19 import 'dart:json'; | 19 import 'dart:json'; |
20 import 'dart:async'; | 20 import 'dart:async'; |
21 | 21 |
22 import 'package:logging/logging.dart'; | 22 import 'package:logging/logging.dart'; |
23 import 'package:markdown/markdown.dart' as markdown; | 23 import 'package:markdown/markdown.dart' as markdown; |
24 import 'package:pathos/path.dart' as path; | 24 import 'package:path/path.dart' as path; |
25 | 25 |
26 import 'dart2yaml.dart'; | 26 import 'dart2yaml.dart'; |
27 import 'src/io.dart'; | 27 import 'src/io.dart'; |
28 import '../../../sdk/lib/_internal/compiler/compiler.dart' as api; | 28 import '../../../sdk/lib/_internal/compiler/compiler.dart' as api; |
29 import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart'; | 29 import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart'; |
30 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirro
r.dart' | 30 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirro
r.dart' |
31 as dart2js; | 31 as dart2js; |
32 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart'
; | 32 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart'
; |
33 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util.
dart'; | 33 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util.
dart'; |
34 import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider.
dart'; | 34 import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider.
dart'; |
35 import '../../../sdk/lib/_internal/libraries.dart'; | 35 import '../../../sdk/lib/_internal/libraries.dart'; |
36 | 36 |
37 var logger = new Logger('Docgen'); | 37 var logger = new Logger('Docgen'); |
38 | 38 |
39 const String USAGE = 'Usage: dart docgen.dart [OPTIONS] [fooDir/barFile]'; | 39 const String USAGE = 'Usage: dart docgen.dart [OPTIONS] [fooDir/barFile]'; |
40 | 40 |
41 /// Current library being documented to be used for comment links. | 41 /// Current library being documented to be used for comment links. |
42 LibraryMirror _currentLibrary; | 42 LibraryMirror _currentLibrary; |
43 | 43 |
44 /// Current class being documented to be used for comment links. | 44 /// Current class being documented to be used for comment links. |
45 ClassMirror _currentClass; | 45 ClassMirror _currentClass; |
46 | 46 |
47 /// Current member being documented to be used for comment links. | 47 /// Current member being documented to be used for comment links. |
48 MemberMirror _currentMember; | 48 MemberMirror _currentMember; |
49 | 49 |
50 /// Resolves reference links in doc comments. | 50 /// Resolves reference links in doc comments. |
51 markdown.Resolver linkResolver; | 51 markdown.Resolver linkResolver; |
52 | 52 |
53 /** | 53 /** |
54 * Docgen constructor initializes the link resolver for markdown parsing. | 54 * Docgen constructor initializes the link resolver for markdown parsing. |
55 * Also initializes the command line arguments. | 55 * Also initializes the command line arguments. |
56 * | 56 * |
57 * [packageRoot] is the packages directory of the directory being analyzed. | 57 * [packageRoot] is the packages directory of the directory being analyzed. |
58 * If [includeSdk] is `true`, then any SDK libraries explicitly imported will | 58 * If [includeSdk] is `true`, then any SDK libraries explicitly imported will |
59 * also be documented. | 59 * also be documented. |
60 * If [parseSdk] is `true`, then all Dart SDK libraries will be documented. | 60 * If [parseSdk] is `true`, then all Dart SDK libraries will be documented. |
61 * This option is useful when only the SDK libraries are needed. | 61 * This option is useful when only the SDK libraries are needed. |
62 * | 62 * |
63 * Returns `true` if docgen sucessfuly completes. | 63 * Returns `true` if docgen sucessfuly completes. |
64 */ | 64 */ |
65 Future<bool> docgen(List<String> files, {String packageRoot, | 65 Future<bool> docgen(List<String> files, {String packageRoot, |
66 bool outputToYaml: true, bool includePrivate: false, bool includeSdk: false, | 66 bool outputToYaml: true, bool includePrivate: false, bool includeSdk: false, |
67 bool parseSdk: false}) { | 67 bool parseSdk: false}) { |
68 if (packageRoot == null && !parseSdk) { | 68 if (packageRoot == null && !parseSdk) { |
69 // TODO(janicejl): At the moment, if a single file is passed it, it is | 69 // TODO(janicejl): At the moment, if a single file is passed it, it is |
70 // assumed that it does not have a package root unless it is passed in by | 70 // assumed that it does not have a package root unless it is passed in by |
71 // the user. In future, find a better way to find the packageRoot and also | 71 // the user. In future, find a better way to find the packageRoot and also |
72 // fully test finding the packageRoot. | 72 // fully test finding the packageRoot. |
73 if (FileSystemEntity.typeSync(files.first) | 73 if (FileSystemEntity.typeSync(files.first) |
74 == FileSystemEntityType.DIRECTORY) { | 74 == FileSystemEntityType.DIRECTORY) { |
75 packageRoot = _findPackageRoot(files.first); | 75 packageRoot = _findPackageRoot(files.first); |
76 } | 76 } |
77 } | 77 } |
78 logger.info('Package Root: ${packageRoot}'); | 78 logger.info('Package Root: ${packageRoot}'); |
79 | 79 |
80 linkResolver = (name) => | 80 linkResolver = (name) => |
81 fixReference(name, _currentLibrary, _currentClass, _currentMember); | 81 fixReference(name, _currentLibrary, _currentClass, _currentMember); |
82 | 82 |
83 return getMirrorSystem(files, packageRoot, parseSdk: parseSdk) | 83 return getMirrorSystem(files, packageRoot, parseSdk: parseSdk) |
84 .then((MirrorSystem mirrorSystem) { | 84 .then((MirrorSystem mirrorSystem) { |
85 if (mirrorSystem.libraries.isEmpty) { | 85 if (mirrorSystem.libraries.isEmpty) { |
86 throw new StateError('No library mirrors were created.'); | 86 throw new StateError('No library mirrors were created.'); |
87 } | 87 } |
88 _documentLibraries(mirrorSystem.libraries.values, | 88 _documentLibraries(mirrorSystem.libraries.values, |
89 includeSdk: includeSdk, includePrivate: includePrivate, | 89 includeSdk: includeSdk, includePrivate: includePrivate, |
90 outputToYaml: outputToYaml); | 90 outputToYaml: outputToYaml); |
91 | 91 |
92 return true; | 92 return true; |
93 }); | 93 }); |
94 } | 94 } |
95 | 95 |
96 List<String> _listLibraries(List<String> args) { | 96 List<String> _listLibraries(List<String> args) { |
97 // TODO(janicejl): At the moment, only have support to have either one file, | 97 // TODO(janicejl): At the moment, only have support to have either one file, |
98 // or one directory. This is because there can only be one package directory | 98 // or one directory. This is because there can only be one package directory |
99 // since only one docgen is created per run. | 99 // since only one docgen is created per run. |
100 if (args.length != 1) throw new UnsupportedError(USAGE); | 100 if (args.length != 1) throw new UnsupportedError(USAGE); |
101 var libraries = new List<String>(); | 101 var libraries = new List<String>(); |
102 var type = FileSystemEntity.typeSync(args[0]); | 102 var type = FileSystemEntity.typeSync(args[0]); |
103 | 103 |
104 if (type == FileSystemEntityType.FILE) { | 104 if (type == FileSystemEntityType.FILE) { |
105 libraries.add(path.absolute(args[0])); | 105 libraries.add(path.absolute(args[0])); |
106 logger.info('Added to libraries: ${libraries.last}'); | 106 logger.info('Added to libraries: ${libraries.last}'); |
107 } else { | 107 } else { |
108 libraries.addAll(_listDartFromDir(args[0])); | 108 libraries.addAll(_listDartFromDir(args[0])); |
109 } | 109 } |
110 return libraries; | 110 return libraries; |
111 } | 111 } |
112 | 112 |
113 List<String> _listDartFromDir(String args) { | 113 List<String> _listDartFromDir(String args) { |
114 var files = listDir(args, recursive: true); | 114 var files = listDir(args, recursive: true); |
115 // To avoid anaylzing package files twice, only files with paths not | 115 // To avoid anaylzing package files twice, only files with paths not |
116 // containing '/packages' will be added. The only exception is if the file to | 116 // containing '/packages' will be added. The only exception is if the file to |
117 // analyze already has a '/package' in its path. | 117 // analyze already has a '/package' in its path. |
118 return files.where((f) => f.endsWith('.dart') && | 118 return files.where((f) => f.endsWith('.dart') && |
119 (!f.contains('/packages') || args.contains('/packages'))).toList() | 119 (!f.contains('/packages') || args.contains('/packages'))).toList() |
120 ..forEach((lib) => logger.info('Added to libraries: $lib')); | 120 ..forEach((lib) => logger.info('Added to libraries: $lib')); |
121 } | 121 } |
122 | 122 |
123 String _findPackageRoot(String directory) { | 123 String _findPackageRoot(String directory) { |
124 var files = listDir(directory, recursive: true); | 124 var files = listDir(directory, recursive: true); |
125 // Return '' means that there was no pubspec.yaml and therefor no packageRoot.
| 125 // Return '' means that there was no pubspec.yaml and therefor no packageRoot. |
126 String packageRoot = files.firstWhere((f) => | 126 String packageRoot = files.firstWhere((f) => |
127 f.endsWith('/pubspec.yaml'), orElse: () => ''); | 127 f.endsWith('/pubspec.yaml'), orElse: () => ''); |
128 if (packageRoot != '') { | 128 if (packageRoot != '') { |
129 packageRoot = path.dirname(packageRoot) + '/packages'; | 129 packageRoot = path.dirname(packageRoot) + '/packages'; |
130 } | 130 } |
131 return packageRoot; | 131 return packageRoot; |
132 } | 132 } |
133 | 133 |
134 List<String> _listSdk() { | 134 List<String> _listSdk() { |
135 var sdk = new List<String>(); | 135 var sdk = new List<String>(); |
136 LIBRARIES.forEach((String name, LibraryInfo info) { | 136 LIBRARIES.forEach((String name, LibraryInfo info) { |
137 if (info.documented) { | 137 if (info.documented) { |
138 sdk.add('dart:$name'); | 138 sdk.add('dart:$name'); |
139 logger.info('Add to SDK: ${sdk.last}'); | 139 logger.info('Add to SDK: ${sdk.last}'); |
140 } | 140 } |
141 }); | 141 }); |
142 return sdk; | 142 return sdk; |
143 } | 143 } |
144 | 144 |
145 /** | 145 /** |
146 * Analyzes set of libraries by getting a mirror system and triggers the | 146 * Analyzes set of libraries by getting a mirror system and triggers the |
147 * documentation of the libraries. | 147 * documentation of the libraries. |
148 */ | 148 */ |
149 Future<MirrorSystem> getMirrorSystem(List<String> args, String packageRoot, | 149 Future<MirrorSystem> getMirrorSystem(List<String> args, String packageRoot, |
150 {bool parseSdk:false}) { | 150 {bool parseSdk:false}) { |
151 var libraries = !parseSdk ? _listLibraries(args) : _listSdk(); | 151 var libraries = !parseSdk ? _listLibraries(args) : _listSdk(); |
152 if (libraries.isEmpty) throw new StateError('No Libraries.'); | 152 if (libraries.isEmpty) throw new StateError('No Libraries.'); |
153 // DART_SDK should be set to the root of the SDK library. | 153 // DART_SDK should be set to the root of the SDK library. |
154 var sdkRoot = Platform.environment['DART_SDK']; | 154 var sdkRoot = Platform.environment['DART_SDK']; |
155 if (sdkRoot != null) { | 155 if (sdkRoot != null) { |
156 logger.info('Using DART_SDK to find SDK at $sdkRoot'); | 156 logger.info('Using DART_SDK to find SDK at $sdkRoot'); |
157 } else { | 157 } else { |
158 // If DART_SDK is not defined in the environment, | 158 // If DART_SDK is not defined in the environment, |
159 // assuming the dart executable is from the Dart SDK folder inside bin. | 159 // assuming the dart executable is from the Dart SDK folder inside bin. |
160 sdkRoot = path.dirname(path.dirname(new Options().executable)); | 160 sdkRoot = path.dirname(path.dirname(new Options().executable)); |
161 logger.info('SDK Root: ${sdkRoot}'); | 161 logger.info('SDK Root: ${sdkRoot}'); |
162 } | 162 } |
163 | 163 |
164 return _analyzeLibraries(libraries, sdkRoot, packageRoot: packageRoot); | 164 return _analyzeLibraries(libraries, sdkRoot, packageRoot: packageRoot); |
165 } | 165 } |
166 | 166 |
167 // TODO(janicejl): Should make docgen fail gracefully, or output a friendly | 167 // TODO(janicejl): Should make docgen fail gracefully, or output a friendly |
168 // error message letting them know why it is failing to create a mirror system. | 168 // error message letting them know why it is failing to create a mirror system. |
169 // If there is conflicting library names, should modify it with a hash at the | 169 // If there is conflicting library names, should modify it with a hash at the |
170 // end of it's library name. | 170 // end of it's library name. |
171 /** | 171 /** |
172 * Analyzes set of libraries and provides a mirror system which can be used | 172 * Analyzes set of libraries and provides a mirror system which can be used |
173 * for static inspection of the source code. | 173 * for static inspection of the source code. |
174 */ | 174 */ |
175 Future<MirrorSystem> _analyzeLibraries(List<String> libraries, | 175 Future<MirrorSystem> _analyzeLibraries(List<String> libraries, |
176 String libraryRoot, {String packageRoot}) { | 176 String libraryRoot, {String packageRoot}) { |
177 SourceFileProvider provider = new SourceFileProvider(); | 177 SourceFileProvider provider = new SourceFileProvider(); |
178 api.DiagnosticHandler diagnosticHandler = | 178 api.DiagnosticHandler diagnosticHandler = |
179 new FormattingDiagnosticHandler(provider).diagnosticHandler; | 179 new FormattingDiagnosticHandler(provider).diagnosticHandler; |
180 Uri libraryUri = currentDirectory.resolve(appendSlash('$libraryRoot')); | 180 Uri libraryUri = currentDirectory.resolve(appendSlash('$libraryRoot')); |
181 Uri packageUri = null; | 181 Uri packageUri = null; |
182 if (packageRoot != null) { | 182 if (packageRoot != null) { |
183 packageUri = currentDirectory.resolve(appendSlash('$packageRoot')); | 183 packageUri = currentDirectory.resolve(appendSlash('$packageRoot')); |
184 } | 184 } |
185 List<Uri> librariesUri = <Uri>[]; | 185 List<Uri> librariesUri = <Uri>[]; |
186 libraries.forEach((library) { | 186 libraries.forEach((library) { |
187 librariesUri.add(currentDirectory.resolve(library)); | 187 librariesUri.add(currentDirectory.resolve(library)); |
188 }); | 188 }); |
189 return dart2js.analyze(librariesUri, libraryUri, packageUri, | 189 return dart2js.analyze(librariesUri, libraryUri, packageUri, |
190 provider.readStringFromUri, diagnosticHandler, | 190 provider.readStringFromUri, diagnosticHandler, |
191 ['--preserve-comments', '--categories=Client,Server']) | 191 ['--preserve-comments', '--categories=Client,Server']) |
192 ..catchError((error) { | 192 ..catchError((error) { |
193 logger.severe('Error: Failed to create mirror system. '); | 193 logger.severe('Error: Failed to create mirror system. '); |
194 // TODO(janicejl): Use the stack trace package when bug is resolved. | 194 // TODO(janicejl): Use the stack trace package when bug is resolved. |
195 // Currently, a string is thrown when it fails to create a mirror | 195 // Currently, a string is thrown when it fails to create a mirror |
196 // system, and it is not possible to use the stack trace. BUG(#11622) | 196 // system, and it is not possible to use the stack trace. BUG(#11622) |
197 // To avoid printing the stack trace. | 197 // To avoid printing the stack trace. |
198 exit(1); | 198 exit(1); |
199 }); | 199 }); |
200 } | 200 } |
201 | 201 |
202 /** | 202 /** |
203 * Creates documentation for filtered libraries. | 203 * Creates documentation for filtered libraries. |
204 */ | 204 */ |
205 void _documentLibraries(List<LibraryMirror> libraries, | 205 void _documentLibraries(List<LibraryMirror> libraries, |
206 {bool includeSdk:false, bool includePrivate:false, bool | 206 {bool includeSdk:false, bool includePrivate:false, bool |
207 outputToYaml:true}) { | 207 outputToYaml:true}) { |
208 libraries.forEach((lib) { | 208 libraries.forEach((lib) { |
209 // Files belonging to the SDK have a uri that begins with 'dart:'. | 209 // Files belonging to the SDK have a uri that begins with 'dart:'. |
210 if (includeSdk || !lib.uri.toString().startsWith('dart:')) { | 210 if (includeSdk || !lib.uri.toString().startsWith('dart:')) { |
211 var library = generateLibrary(lib, includePrivate: includePrivate); | 211 var library = generateLibrary(lib, includePrivate: includePrivate); |
212 _writeLibraryToFile(library, outputToYaml); | 212 _writeLibraryToFile(library, outputToYaml); |
213 } | 213 } |
214 }); | 214 }); |
215 // Outputs a text file with a list of files available after creating all | 215 // Outputs a text file with a list of files available after creating all |
216 // the libraries. This will help the viewer know what files are available | 216 // the libraries. This will help the viewer know what files are available |
217 // to read in. | 217 // to read in. |
218 _writeToFile(listDir('docs').join('\n').replaceAll('docs/', ''), | 218 _writeToFile(listDir('docs').join('\n').replaceAll('docs/', ''), |
219 'library_list.txt'); | 219 'library_list.txt'); |
220 } | 220 } |
221 | 221 |
222 Library generateLibrary(dart2js.Dart2JsLibraryMirror library, | 222 Library generateLibrary(dart2js.Dart2JsLibraryMirror library, |
223 {bool includePrivate:false}) { | 223 {bool includePrivate:false}) { |
224 _currentLibrary = library; | 224 _currentLibrary = library; |
225 var result = new Library(library.qualifiedName, _getComment(library), | 225 var result = new Library(library.qualifiedName, _getComment(library), |
226 _getVariables(library.variables, includePrivate), | 226 _getVariables(library.variables, includePrivate), |
227 _getMethods(library.functions, includePrivate), | 227 _getMethods(library.functions, includePrivate), |
228 _getClasses(library.classes, includePrivate)); | 228 _getClasses(library.classes, includePrivate)); |
229 logger.fine('Generated library for ${result.name}'); | 229 logger.fine('Generated library for ${result.name}'); |
230 return result; | 230 return result; |
231 } | 231 } |
232 | 232 |
233 void _writeLibraryToFile(Library result, bool outputToYaml) { | 233 void _writeLibraryToFile(Library result, bool outputToYaml) { |
234 if (outputToYaml) { | 234 if (outputToYaml) { |
235 _writeToFile(getYamlString(result.toMap()), '${result.name}.yaml'); | 235 _writeToFile(getYamlString(result.toMap()), '${result.name}.yaml'); |
236 } else { | 236 } else { |
237 _writeToFile(stringify(result.toMap()), '${result.name}.json'); | 237 _writeToFile(stringify(result.toMap()), '${result.name}.json'); |
238 } | 238 } |
239 | 239 |
240 } | 240 } |
241 | 241 |
242 /** | 242 /** |
243 * Returns a list of meta annotations assocated with a mirror. | 243 * Returns a list of meta annotations assocated with a mirror. |
244 */ | 244 */ |
245 List<String> _getAnnotations(DeclarationMirror mirror) { | 245 List<String> _getAnnotations(DeclarationMirror mirror) { |
246 var annotations = mirror.metadata.where((e) => | 246 var annotations = mirror.metadata.where((e) => |
247 e is dart2js.Dart2JsConstructedConstantMirror); | 247 e is dart2js.Dart2JsConstructedConstantMirror); |
248 return annotations.map((e) => e.type.qualifiedName).toList(); | 248 return annotations.map((e) => e.type.qualifiedName).toList(); |
249 } | 249 } |
250 | 250 |
251 /** | 251 /** |
252 * Returns any documentation comments associated with a mirror with | 252 * Returns any documentation comments associated with a mirror with |
253 * simple markdown converted to html. | 253 * simple markdown converted to html. |
254 */ | 254 */ |
255 String _getComment(DeclarationMirror mirror) { | 255 String _getComment(DeclarationMirror mirror) { |
256 String commentText; | 256 String commentText; |
257 mirror.metadata.forEach((metadata) { | 257 mirror.metadata.forEach((metadata) { |
258 if (metadata is CommentInstanceMirror) { | 258 if (metadata is CommentInstanceMirror) { |
259 CommentInstanceMirror comment = metadata; | 259 CommentInstanceMirror comment = metadata; |
260 if (comment.isDocComment) { | 260 if (comment.isDocComment) { |
261 if (commentText == null) { | 261 if (commentText == null) { |
262 commentText = comment.trimmedText; | 262 commentText = comment.trimmedText; |
263 } else { | 263 } else { |
264 commentText = '$commentText ${comment.trimmedText}'; | 264 commentText = '$commentText ${comment.trimmedText}'; |
265 } | 265 } |
266 } | 266 } |
267 } | 267 } |
268 }); | 268 }); |
269 commentText = commentText == null ? '' : | 269 commentText = commentText == null ? '' : |
270 markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver) | 270 markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver) |
271 .replaceAll('\n', ' '); | 271 .replaceAll('\n', ' '); |
272 return commentText; | 272 return commentText; |
273 } | 273 } |
274 | 274 |
275 /** | 275 /** |
276 * Converts all [foo] references in comments to <a>libraryName.foo</a>. | 276 * Converts all [foo] references in comments to <a>libraryName.foo</a>. |
277 */ | 277 */ |
278 markdown.Node fixReference(String name, LibraryMirror currentLibrary, | 278 markdown.Node fixReference(String name, LibraryMirror currentLibrary, |
279 ClassMirror currentClass, MemberMirror currentMember) { | 279 ClassMirror currentClass, MemberMirror currentMember) { |
280 var reference; | 280 var reference; |
281 var memberScope = currentMember == null ? | 281 var memberScope = currentMember == null ? |
282 null : currentMember.lookupInScope(name); | 282 null : currentMember.lookupInScope(name); |
283 if (memberScope != null) reference = memberScope.qualifiedName; | 283 if (memberScope != null) reference = memberScope.qualifiedName; |
284 else { | 284 else { |
285 var classScope = currentClass == null ? | 285 var classScope = currentClass == null ? |
286 null : currentClass.lookupInScope(name); | 286 null : currentClass.lookupInScope(name); |
287 reference = classScope != null ? classScope.qualifiedName : name; | 287 reference = classScope != null ? classScope.qualifiedName : name; |
288 } | 288 } |
289 return new markdown.Element.text('a', reference); | 289 return new markdown.Element.text('a', reference); |
290 } | 290 } |
291 | 291 |
292 /** | 292 /** |
293 * Returns a map of [Variable] objects constructed from inputted mirrors. | 293 * Returns a map of [Variable] objects constructed from inputted mirrors. |
294 */ | 294 */ |
295 Map<String, Variable> _getVariables(Map<String, VariableMirror> mirrorMap, | 295 Map<String, Variable> _getVariables(Map<String, VariableMirror> mirrorMap, |
296 bool includePrivate) { | 296 bool includePrivate) { |
297 var data = {}; | 297 var data = {}; |
298 // TODO(janicejl): When map to map feature is created, replace the below with | 298 // TODO(janicejl): When map to map feature is created, replace the below with |
299 // a filter. Issue(#9590). | 299 // a filter. Issue(#9590). |
300 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { | 300 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { |
301 if (includePrivate || !mirror.isPrivate) { | 301 if (includePrivate || !mirror.isPrivate) { |
302 _currentMember = mirror; | 302 _currentMember = mirror; |
303 data[mirrorName] = new Variable(mirrorName, mirror.qualifiedName, | 303 data[mirrorName] = new Variable(mirrorName, mirror.qualifiedName, |
304 mirror.isFinal, mirror.isStatic, mirror.type.qualifiedName, | 304 mirror.isFinal, mirror.isStatic, mirror.type.qualifiedName, |
305 _getComment(mirror), _getAnnotations(mirror)); | 305 _getComment(mirror), _getAnnotations(mirror)); |
306 } | 306 } |
307 }); | 307 }); |
308 return data; | 308 return data; |
309 } | 309 } |
310 | 310 |
311 /** | 311 /** |
312 * Returns a map of [Method] objects constructed from inputted mirrors. | 312 * Returns a map of [Method] objects constructed from inputted mirrors. |
313 */ | 313 */ |
314 Map<String, Method> _getMethods(Map<String, MethodMirror> mirrorMap, | 314 Map<String, Method> _getMethods(Map<String, MethodMirror> mirrorMap, |
315 bool includePrivate) { | 315 bool includePrivate) { |
316 var data = {}; | 316 var data = {}; |
317 mirrorMap.forEach((String mirrorName, MethodMirror mirror) { | 317 mirrorMap.forEach((String mirrorName, MethodMirror mirror) { |
318 if (includePrivate || !mirror.isPrivate) { | 318 if (includePrivate || !mirror.isPrivate) { |
319 _currentMember = mirror; | 319 _currentMember = mirror; |
320 data[mirrorName] = new Method(mirrorName, mirror.qualifiedName, | 320 data[mirrorName] = new Method(mirrorName, mirror.qualifiedName, |
321 mirror.isSetter, mirror.isGetter, mirror.isConstructor, | 321 mirror.isSetter, mirror.isGetter, mirror.isConstructor, |
322 mirror.isOperator, mirror.isStatic, mirror.returnType.qualifiedName, | 322 mirror.isOperator, mirror.isStatic, mirror.returnType.qualifiedName, |
323 _getComment(mirror), _getParameters(mirror.parameters), | 323 _getComment(mirror), _getParameters(mirror.parameters), |
324 _getAnnotations(mirror)); | 324 _getAnnotations(mirror)); |
325 } | 325 } |
326 }); | 326 }); |
327 return data; | 327 return data; |
328 } | 328 } |
329 | 329 |
330 /** | 330 /** |
331 * Returns a map of [Class] objects constructed from inputted mirrors. | 331 * Returns a map of [Class] objects constructed from inputted mirrors. |
332 */ | 332 */ |
333 Map<String, Class> _getClasses(Map<String, ClassMirror> mirrorMap, | 333 Map<String, Class> _getClasses(Map<String, ClassMirror> mirrorMap, |
334 bool includePrivate) { | 334 bool includePrivate) { |
335 var data = {}; | 335 var data = {}; |
336 mirrorMap.forEach((String mirrorName, ClassMirror mirror) { | 336 mirrorMap.forEach((String mirrorName, ClassMirror mirror) { |
337 if (includePrivate || !mirror.isPrivate) { | 337 if (includePrivate || !mirror.isPrivate) { |
338 _currentClass = mirror; | 338 _currentClass = mirror; |
339 var superclass = (mirror.superclass != null) ? | 339 var superclass = (mirror.superclass != null) ? |
340 mirror.superclass.qualifiedName : ''; | 340 mirror.superclass.qualifiedName : ''; |
341 var interfaces = | 341 var interfaces = |
342 mirror.superinterfaces.map((interface) => interface.qualifiedName); | 342 mirror.superinterfaces.map((interface) => interface.qualifiedName); |
343 data[mirrorName] = new Class(mirrorName, mirror.qualifiedName, | 343 data[mirrorName] = new Class(mirrorName, mirror.qualifiedName, |
344 superclass, mirror.isAbstract, mirror.isTypedef, | 344 superclass, mirror.isAbstract, mirror.isTypedef, |
345 _getComment(mirror), interfaces.toList(), | 345 _getComment(mirror), interfaces.toList(), |
346 _getVariables(mirror.variables, includePrivate), | 346 _getVariables(mirror.variables, includePrivate), |
347 _getMethods(mirror.methods, includePrivate), | 347 _getMethods(mirror.methods, includePrivate), |
348 _getAnnotations(mirror)); | 348 _getAnnotations(mirror)); |
349 } | 349 } |
350 }); | 350 }); |
351 return data; | 351 return data; |
352 } | 352 } |
353 | 353 |
354 /** | 354 /** |
355 * Returns a map of [Parameter] objects constructed from inputted mirrors. | 355 * Returns a map of [Parameter] objects constructed from inputted mirrors. |
356 */ | 356 */ |
357 Map<String, Parameter> _getParameters(List<ParameterMirror> mirrorList) { | 357 Map<String, Parameter> _getParameters(List<ParameterMirror> mirrorList) { |
358 var data = {}; | 358 var data = {}; |
359 mirrorList.forEach((ParameterMirror mirror) { | 359 mirrorList.forEach((ParameterMirror mirror) { |
360 _currentMember = mirror; | 360 _currentMember = mirror; |
361 data[mirror.simpleName] = new Parameter(mirror.simpleName, | 361 data[mirror.simpleName] = new Parameter(mirror.simpleName, |
362 mirror.qualifiedName, mirror.isOptional, mirror.isNamed, | 362 mirror.qualifiedName, mirror.isOptional, mirror.isNamed, |
363 mirror.hasDefaultValue, mirror.type.qualifiedName, | 363 mirror.hasDefaultValue, mirror.type.qualifiedName, |
364 mirror.defaultValue, _getAnnotations(mirror)); | 364 mirror.defaultValue, _getAnnotations(mirror)); |
365 }); | 365 }); |
366 return data; | 366 return data; |
367 } | 367 } |
368 | 368 |
369 /** | 369 /** |
370 * Writes text to a file in the 'docs' directory. | 370 * Writes text to a file in the 'docs' directory. |
371 */ | 371 */ |
372 void _writeToFile(String text, String filename) { | 372 void _writeToFile(String text, String filename) { |
373 Directory dir = new Directory('docs'); | 373 Directory dir = new Directory('docs'); |
(...skipping 16 matching lines...) Expand all Loading... |
390 inputMap.forEach((key, value) { | 390 inputMap.forEach((key, value) { |
391 outputMap[key] = value.toMap(); | 391 outputMap[key] = value.toMap(); |
392 }); | 392 }); |
393 return outputMap; | 393 return outputMap; |
394 } | 394 } |
395 | 395 |
396 /** | 396 /** |
397 * A class containing contents of a Dart library. | 397 * A class containing contents of a Dart library. |
398 */ | 398 */ |
399 class Library { | 399 class Library { |
400 | 400 |
401 /// Documentation comment with converted markdown. | 401 /// Documentation comment with converted markdown. |
402 String comment; | 402 String comment; |
403 | 403 |
404 /// Top-level variables in the library. | 404 /// Top-level variables in the library. |
405 Map<String, Variable> variables; | 405 Map<String, Variable> variables; |
406 | 406 |
407 /// Top-level functions in the library. | 407 /// Top-level functions in the library. |
408 Map<String, Method> functions; | 408 Map<String, Method> functions; |
409 | 409 |
410 /// Classes defined within the library | 410 /// Classes defined within the library |
411 Map<String, Class> classes; | 411 Map<String, Class> classes; |
412 | 412 |
413 String name; | 413 String name; |
414 | 414 |
415 Library(this.name, this.comment, this.variables, | 415 Library(this.name, this.comment, this.variables, |
416 this.functions, this.classes); | 416 this.functions, this.classes); |
417 | 417 |
418 /// Generates a map describing the [Library] object. | 418 /// Generates a map describing the [Library] object. |
419 Map toMap() { | 419 Map toMap() { |
420 var libraryMap = {}; | 420 var libraryMap = {}; |
421 libraryMap['name'] = name; | 421 libraryMap['name'] = name; |
422 libraryMap['comment'] = comment; | 422 libraryMap['comment'] = comment; |
423 libraryMap['variables'] = recurseMap(variables); | 423 libraryMap['variables'] = recurseMap(variables); |
424 libraryMap['functions'] = recurseMap(functions); | 424 libraryMap['functions'] = recurseMap(functions); |
425 libraryMap['classes'] = recurseMap(classes); | 425 libraryMap['classes'] = recurseMap(classes); |
426 return libraryMap; | 426 return libraryMap; |
427 } | 427 } |
428 } | 428 } |
429 | 429 |
430 /** | 430 /** |
431 * A class containing contents of a Dart class. | 431 * A class containing contents of a Dart class. |
432 */ | 432 */ |
433 // TODO(tmandel): Figure out how to do typedefs (what is needed) | 433 // TODO(tmandel): Figure out how to do typedefs (what is needed) |
434 class Class { | 434 class Class { |
435 | 435 |
436 /// Documentation comment with converted markdown. | 436 /// Documentation comment with converted markdown. |
437 String comment; | 437 String comment; |
438 | 438 |
439 /// List of the names of interfaces that this class implements. | 439 /// List of the names of interfaces that this class implements. |
440 List<String> interfaces; | 440 List<String> interfaces; |
441 | 441 |
442 /// Top-level variables in the class. | 442 /// Top-level variables in the class. |
443 Map<String, Variable> variables; | 443 Map<String, Variable> variables; |
444 | 444 |
445 /// Methods in the class. | 445 /// Methods in the class. |
446 Map<String, Method> methods; | 446 Map<String, Method> methods; |
447 | 447 |
448 String name; | 448 String name; |
449 String qualifiedName; | 449 String qualifiedName; |
450 String superclass; | 450 String superclass; |
451 bool isAbstract; | 451 bool isAbstract; |
452 bool isTypedef; | 452 bool isTypedef; |
453 | 453 |
454 /// List of the meta annotations on the class. | 454 /// List of the meta annotations on the class. |
455 List<String> annotations; | 455 List<String> annotations; |
456 | 456 |
457 Class(this.name, this.qualifiedName, this.superclass, this.isAbstract, | 457 Class(this.name, this.qualifiedName, this.superclass, this.isAbstract, |
458 this.isTypedef, this.comment, this.interfaces, this.variables, | 458 this.isTypedef, this.comment, this.interfaces, this.variables, |
459 this.methods, this.annotations); | 459 this.methods, this.annotations); |
460 | 460 |
461 /// Generates a map describing the [Class] object. | 461 /// Generates a map describing the [Class] object. |
462 Map toMap() { | 462 Map toMap() { |
463 var classMap = {}; | 463 var classMap = {}; |
464 classMap['name'] = name; | 464 classMap['name'] = name; |
465 classMap['qualifiedname'] = qualifiedName; | 465 classMap['qualifiedname'] = qualifiedName; |
466 classMap['comment'] = comment; | 466 classMap['comment'] = comment; |
467 classMap['superclass'] = superclass; | 467 classMap['superclass'] = superclass; |
468 classMap['abstract'] = isAbstract.toString(); | 468 classMap['abstract'] = isAbstract.toString(); |
469 classMap['typedef'] = isTypedef.toString(); | 469 classMap['typedef'] = isTypedef.toString(); |
470 classMap['implements'] = new List.from(interfaces); | 470 classMap['implements'] = new List.from(interfaces); |
471 classMap['variables'] = recurseMap(variables); | 471 classMap['variables'] = recurseMap(variables); |
472 classMap['methods'] = recurseMap(methods); | 472 classMap['methods'] = recurseMap(methods); |
473 classMap['annotations'] = new List.from(annotations); | 473 classMap['annotations'] = new List.from(annotations); |
474 return classMap; | 474 return classMap; |
475 } | 475 } |
476 } | 476 } |
477 | 477 |
478 /** | 478 /** |
479 * A class containing properties of a Dart variable. | 479 * A class containing properties of a Dart variable. |
480 */ | 480 */ |
481 class Variable { | 481 class Variable { |
482 | 482 |
483 /// Documentation comment with converted markdown. | 483 /// Documentation comment with converted markdown. |
484 String comment; | 484 String comment; |
485 | 485 |
486 String name; | 486 String name; |
487 String qualifiedName; | 487 String qualifiedName; |
488 bool isFinal; | 488 bool isFinal; |
489 bool isStatic; | 489 bool isStatic; |
490 String type; | 490 String type; |
491 | 491 |
492 /// List of the meta annotations on the variable. | 492 /// List of the meta annotations on the variable. |
493 List<String> annotations; | 493 List<String> annotations; |
494 | 494 |
495 Variable(this.name, this.qualifiedName, this.isFinal, this.isStatic, | 495 Variable(this.name, this.qualifiedName, this.isFinal, this.isStatic, |
496 this.type, this.comment, this.annotations); | 496 this.type, this.comment, this.annotations); |
497 | 497 |
498 /// Generates a map describing the [Variable] object. | 498 /// Generates a map describing the [Variable] object. |
499 Map toMap() { | 499 Map toMap() { |
500 var variableMap = {}; | 500 var variableMap = {}; |
501 variableMap['name'] = name; | 501 variableMap['name'] = name; |
502 variableMap['qualifiedname'] = qualifiedName; | 502 variableMap['qualifiedname'] = qualifiedName; |
503 variableMap['comment'] = comment; | 503 variableMap['comment'] = comment; |
504 variableMap['final'] = isFinal.toString(); | 504 variableMap['final'] = isFinal.toString(); |
505 variableMap['static'] = isStatic.toString(); | 505 variableMap['static'] = isStatic.toString(); |
506 variableMap['type'] = type; | 506 variableMap['type'] = type; |
507 variableMap['annotations'] = new List.from(annotations); | 507 variableMap['annotations'] = new List.from(annotations); |
508 return variableMap; | 508 return variableMap; |
509 } | 509 } |
510 } | 510 } |
511 | 511 |
512 /** | 512 /** |
513 * A class containing properties of a Dart method. | 513 * A class containing properties of a Dart method. |
514 */ | 514 */ |
515 class Method { | 515 class Method { |
516 | 516 |
517 /// Documentation comment with converted markdown. | 517 /// Documentation comment with converted markdown. |
518 String comment; | 518 String comment; |
519 | 519 |
520 /// Parameters for this method. | 520 /// Parameters for this method. |
521 Map<String, Parameter> parameters; | 521 Map<String, Parameter> parameters; |
522 | 522 |
523 String name; | 523 String name; |
524 String qualifiedName; | 524 String qualifiedName; |
525 bool isSetter; | 525 bool isSetter; |
526 bool isGetter; | 526 bool isGetter; |
527 bool isConstructor; | 527 bool isConstructor; |
528 bool isOperator; | 528 bool isOperator; |
529 bool isStatic; | 529 bool isStatic; |
530 String returnType; | 530 String returnType; |
531 | 531 |
532 /// List of the meta annotations on the method. | 532 /// List of the meta annotations on the method. |
533 List<String> annotations; | 533 List<String> annotations; |
534 | 534 |
535 Method(this.name, this.qualifiedName, this.isSetter, this.isGetter, | 535 Method(this.name, this.qualifiedName, this.isSetter, this.isGetter, |
536 this.isConstructor, this.isOperator, this.isStatic, this.returnType, | 536 this.isConstructor, this.isOperator, this.isStatic, this.returnType, |
537 this.comment, this.parameters, this.annotations); | 537 this.comment, this.parameters, this.annotations); |
538 | 538 |
539 /// Generates a map describing the [Method] object. | 539 /// Generates a map describing the [Method] object. |
540 Map toMap() { | 540 Map toMap() { |
541 var methodMap = {}; | 541 var methodMap = {}; |
542 methodMap['name'] = name; | 542 methodMap['name'] = name; |
543 methodMap['qualifiedname'] = qualifiedName; | 543 methodMap['qualifiedname'] = qualifiedName; |
544 methodMap['comment'] = comment; | 544 methodMap['comment'] = comment; |
545 methodMap['type'] = isSetter ? 'setter' : isGetter ? 'getter' : | 545 methodMap['type'] = isSetter ? 'setter' : isGetter ? 'getter' : |
546 isOperator ? 'operator' : isConstructor ? 'constructor' : 'method'; | 546 isOperator ? 'operator' : isConstructor ? 'constructor' : 'method'; |
547 methodMap['static'] = isStatic.toString(); | 547 methodMap['static'] = isStatic.toString(); |
548 methodMap['return'] = returnType; | 548 methodMap['return'] = returnType; |
549 methodMap['parameters'] = recurseMap(parameters); | 549 methodMap['parameters'] = recurseMap(parameters); |
550 methodMap['annotations'] = new List.from(annotations); | 550 methodMap['annotations'] = new List.from(annotations); |
551 return methodMap; | 551 return methodMap; |
552 } | 552 } |
553 } | 553 } |
554 | 554 |
555 /** | 555 /** |
556 * A class containing properties of a Dart method/function parameter. | 556 * A class containing properties of a Dart method/function parameter. |
557 */ | 557 */ |
558 class Parameter { | 558 class Parameter { |
559 | 559 |
560 String name; | 560 String name; |
561 String qualifiedName; | 561 String qualifiedName; |
562 bool isOptional; | 562 bool isOptional; |
563 bool isNamed; | 563 bool isNamed; |
564 bool hasDefaultValue; | 564 bool hasDefaultValue; |
565 String type; | 565 String type; |
566 String defaultValue; | 566 String defaultValue; |
567 | 567 |
568 /// List of the meta annotations on the parameter. | 568 /// List of the meta annotations on the parameter. |
569 List<String> annotations; | 569 List<String> annotations; |
570 | 570 |
571 Parameter(this.name, this.qualifiedName, this.isOptional, this.isNamed, | 571 Parameter(this.name, this.qualifiedName, this.isOptional, this.isNamed, |
572 this.hasDefaultValue, this.type, this.defaultValue, this.annotations); | 572 this.hasDefaultValue, this.type, this.defaultValue, this.annotations); |
573 | 573 |
574 /// Generates a map describing the [Parameter] object. | 574 /// Generates a map describing the [Parameter] object. |
575 Map toMap() { | 575 Map toMap() { |
576 var parameterMap = {}; | 576 var parameterMap = {}; |
577 parameterMap['name'] = name; | 577 parameterMap['name'] = name; |
578 parameterMap['qualifiedname'] = qualifiedName; | 578 parameterMap['qualifiedname'] = qualifiedName; |
579 parameterMap['optional'] = isOptional.toString(); | 579 parameterMap['optional'] = isOptional.toString(); |
580 parameterMap['named'] = isNamed.toString(); | 580 parameterMap['named'] = isNamed.toString(); |
581 parameterMap['default'] = hasDefaultValue.toString(); | 581 parameterMap['default'] = hasDefaultValue.toString(); |
582 parameterMap['type'] = type; | 582 parameterMap['type'] = type; |
583 parameterMap['value'] = defaultValue; | 583 parameterMap['value'] = defaultValue; |
584 parameterMap['annotations'] = new List.from(annotations); | 584 parameterMap['annotations'] = new List.from(annotations); |
585 return parameterMap; | 585 return parameterMap; |
586 } | 586 } |
587 } | 587 } |
OLD | NEW |