Chromium Code Reviews| 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:args/args.dart'; | 22 import 'package:args/args.dart'; |
| 23 import 'package:logging/logging.dart'; | 23 import 'package:logging/logging.dart'; |
| 24 import 'package:markdown/markdown.dart' as markdown; | 24 import 'package:markdown/markdown.dart' as markdown; |
| 25 import 'package:pathos/path.dart' as path; | |
| 25 | 26 |
| 26 import 'dart2yaml.dart'; | 27 import 'dart2yaml.dart'; |
| 28 import 'src/io.dart'; | |
| 27 import '../../../sdk/lib/_internal/compiler/compiler.dart' as api; | 29 import '../../../sdk/lib/_internal/compiler/compiler.dart' as api; |
| 28 import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart'; | 30 import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart'; |
| 29 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirro r.dart' | 31 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirro r.dart' |
| 30 as dart2js; | 32 as dart2js; |
| 31 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart' ; | 33 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart' ; |
| 32 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util. dart'; | 34 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util. dart'; |
| 33 import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider. dart'; | 35 import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider. dart'; |
| 34 | 36 |
| 35 var logger = new Logger("Docgen"); | 37 var logger = new Logger('Docgen'); |
| 36 | 38 |
| 37 /// Counter used to provide unique IDs for each distinct item. | 39 const String usage = 'Usage: dart docgen.dart [OPTIONS] [fooDir/barFile]'; |
| 38 int _nextID = 0; | |
| 39 | |
| 40 int get nextID => _nextID++; | |
| 41 | |
| 42 const String usage = "Usage: dart docgen.dart [OPTIONS] [fooDir/barFile]"; | |
| 43 | |
| 44 List<Path> listLibraries(List<String> args) { | |
| 45 if (args.length != 1) { | |
| 46 throw new UnsupportedError(usage); | |
| 47 } | |
| 48 var libraries = new List<Path>(); | |
| 49 var type = FileSystemEntity.typeSync(args[0]); | |
| 50 | |
| 51 if (type == FileSystemEntityType.NOT_FOUND) { | |
| 52 throw new UnsupportedError("File does not exist. $usage"); | |
| 53 } else if (type == FileSystemEntityType.LINK) { | |
| 54 libraries.addAll(listLibrariesFromDir(new Link(args[0]).targetSync())); | |
| 55 } else if (type == FileSystemEntityType.FILE) { | |
| 56 libraries.add(new Path(args[0])); | |
| 57 logger.info("Added to libraries: ${libraries.last.toString()}"); | |
| 58 } else if (type == FileSystemEntityType.DIRECTORY) { | |
| 59 libraries.addAll(listLibrariesFromDir(args[0])); | |
| 60 } | |
| 61 return libraries; | |
| 62 } | |
| 63 | |
| 64 List<Path> listLibrariesFromDir(String path) { | |
| 65 var libraries = new List<Path>(); | |
| 66 new Directory(path).listSync(recursive: true, | |
| 67 followLinks: true).forEach((file) { | |
| 68 if (new Path(file.path).extension == "dart") { | |
| 69 if (!file.path.contains("/packages/")) { | |
| 70 libraries.add(new Path(file.path)); | |
| 71 logger.info("Added to libraries: ${libraries.last.toString()}"); | |
| 72 } | |
| 73 } | |
| 74 }); | |
| 75 return libraries; | |
| 76 } | |
| 77 | 40 |
| 78 /** | 41 /** |
| 79 * This class documents a list of libraries. | 42 * This class documents a list of libraries. |
| 80 */ | 43 */ |
| 81 class Docgen { | 44 class Docgen { |
| 82 | 45 |
| 83 /// Libraries to be documented. | 46 /// Libraries to be documented. |
| 84 List<LibraryMirror> _libraries; | 47 List<LibraryMirror> _libraries; |
| 85 | 48 |
| 86 /// Current library being documented to be used for comment links. | 49 /// Current library being documented to be used for comment links. |
| 87 LibraryMirror _currentLibrary; | 50 LibraryMirror _currentLibrary; |
| 88 | 51 |
| 89 /// Current class being documented to be used for comment links. | 52 /// Current class being documented to be used for comment links. |
| 90 ClassMirror _currentClass; | 53 ClassMirror _currentClass; |
| 91 | 54 |
| 92 /// Current member being documented to be used for comment links. | 55 /// Current member being documented to be used for comment links. |
| 93 MemberMirror _currentMember; | 56 MemberMirror _currentMember; |
| 94 | 57 |
| 95 /// Resolves reference links | 58 /// Resolves reference links in doc-comments. |
|
Andrei Mouravski
2013/06/25 20:13:22
"doc comments."
janicejl
2013/06/25 20:50:15
Done.
| |
| 96 markdown.Resolver linkResolver; | 59 markdown.Resolver linkResolver; |
| 97 | 60 |
| 61 /// Package Directory of directory being analyzed. | |
|
Andrei Mouravski
2013/06/25 20:13:22
Directory -> directory.
janicejl
2013/06/25 20:50:15
Done.
| |
| 62 String packageDir; | |
| 63 | |
| 98 bool outputToYaml; | 64 bool outputToYaml; |
| 99 bool outputToJson; | 65 bool outputToJson; |
| 100 bool includePrivate; | 66 bool includePrivate; |
| 101 /// State for whether or not the SDK libraries should also be outputted. | 67 /// State for whether or not the SDK libraries should also be outputted. |
| 102 bool includeSdk; | 68 bool includeSdk; |
| 103 | 69 |
| 104 /** | 70 /** |
| 105 * Docgen constructor initializes the link resolver for markdown parsing. | 71 * Docgen constructor initializes the link resolver for markdown parsing. |
| 106 * Also initializes the command line arguments. | 72 * Also initializes the command line arguments. |
| 107 */ | 73 */ |
| 108 Docgen(ArgResults argResults) { | 74 Docgen(ArgResults argResults) { |
| 109 if (argResults["output-format"] == null) { | 75 if (argResults['output-format'] == null) { |
| 110 outputToYaml = | 76 outputToYaml = |
| 111 (argResults["yaml"] == false && argResults["json"] == false) ? | 77 (argResults['yaml'] == false && argResults['json'] == false) ? |
| 112 true : argResults["yaml"]; | 78 true : argResults['yaml']; |
| 113 } else { | 79 } else { |
| 114 if ((argResults["output-format"] == "yaml" && | 80 if ((argResults['output-format'] == 'yaml' && |
| 115 argResults["json"] == true) || | 81 argResults['json'] == true) || |
| 116 (argResults["output-format"] == "json" && | 82 (argResults['output-format'] == 'json' && |
| 117 argResults["yaml"] == true)) { | 83 argResults['yaml'] == true)) { |
| 118 throw new UnsupportedError("Cannot have contradictory output flags."); | 84 throw new UnsupportedError('Cannot have contradictory output flags.'); |
| 119 } | 85 } |
| 120 outputToYaml = argResults["output-format"] == "yaml" ? true : false; | 86 outputToYaml = argResults['output-format'] == 'yaml' ? true : false; |
| 121 } | 87 } |
| 122 outputToJson = !outputToYaml; | 88 outputToJson = !outputToYaml; |
| 123 includePrivate = argResults["include-private"]; | 89 includePrivate = argResults['include-private']; |
| 124 includeSdk = argResults["include-sdk"]; | 90 includeSdk = argResults['include-sdk']; |
| 125 | 91 |
| 126 this.linkResolver = (name) => | 92 this.linkResolver = (name) => |
| 127 fixReference(name, _currentLibrary, _currentClass, _currentMember); | 93 fixReference(name, _currentLibrary, _currentClass, _currentMember); |
| 94 | |
| 95 analyze(argResults.rest); | |
| 128 } | 96 } |
| 129 | 97 |
| 98 List<String> listLibraries(List<String> args) { | |
| 99 if (args.length != 1) throw new UnsupportedError(usage); | |
|
Andrei Mouravski
2013/06/25 20:13:22
Add a TODO here as to why it needs to be this way.
janicejl
2013/06/25 20:50:15
Done.
| |
| 100 var libraries = new List<String>(); | |
| 101 var type = FileSystemEntity.typeSync(args[0]); | |
| 102 | |
| 103 if (type == FileSystemEntityType.LINK) { | |
| 104 libraries.addAll(listDartFromDir(resolveLink(args[0]))); | |
| 105 } else if (type == FileSystemEntityType.FILE) { | |
| 106 libraries.add(path.absolute(args[0])); | |
| 107 logger.info('Added to libraries: ${libraries.last}'); | |
| 108 packageDir = ''; | |
| 109 } else if (type == FileSystemEntityType.DIRECTORY) { | |
| 110 libraries.addAll(listDartFromDir(args[0])); | |
| 111 } else { | |
| 112 throw new UnsupportedError('File does not exist. $usage'); | |
| 113 } | |
| 114 logger.info('Package Directory: $packageDir'); | |
| 115 return libraries; | |
| 116 } | |
| 117 | |
| 118 List<String> listDartFromDir(String args) { | |
| 119 var files = listDir(args, recursive: true); | |
| 120 var libraries = files.where((f) => | |
| 121 f.endsWith('.dart') && !f.contains('/packages')).toList(); | |
| 122 libraries.forEach((lib) => logger.info('Added to libraries: $lib')); | |
| 123 packageDir = files.firstWhere((f) => | |
| 124 f.endsWith('/pubspec.yaml'), orElse: () => ''); | |
| 125 if (packageDir != '') packageDir = path.dirname(packageDir) + '/packages'; | |
| 126 return libraries; | |
| 127 } | |
| 128 | |
| 130 /** | 129 /** |
| 131 * Analyzes set of libraries by getting a mirror system and triggers the | 130 * Analyzes set of libraries by getting a mirror system and triggers the |
| 132 * documentation of the libraries. | 131 * documentation of the libraries. |
| 133 */ | 132 */ |
| 134 void analyze(List<Path> libraries) { | 133 void analyze(List<String> args) { |
| 134 var libraries = listLibraries(args); | |
| 135 if (libraries.isEmpty) throw new UnsupportedError('No Libraries.'); | |
|
Andrei Mouravski
2013/06/25 20:13:22
Because you check isEmpty here, you don't need to
Andrei Mouravski
2013/06/25 20:13:22
Make a more descriptive error.
Also, it's possibly
janicejl
2013/06/25 20:50:15
Done.
| |
| 135 // DART_SDK should be set to the root of the SDK library. | 136 // DART_SDK should be set to the root of the SDK library. |
| 136 var sdkRoot = Platform.environment["DART_SDK"]; | 137 var sdkRoot = Platform.environment['DART_SDK']; |
| 137 if (sdkRoot != null) { | 138 if (sdkRoot != null) { |
| 138 logger.info("Using DART_SDK to find SDK at $sdkRoot"); | 139 logger.info('Using DART_SDK to find SDK at $sdkRoot'); |
| 139 sdkRoot = new Path(sdkRoot); | |
| 140 } else { | 140 } else { |
| 141 // If DART_SDK is not defined in the environment, | 141 // If DART_SDK is not defined in the environment, |
| 142 // assuming the dart executable is from the Dart SDK folder inside bin. | 142 // assuming the dart executable is from the Dart SDK folder inside bin. |
| 143 sdkRoot = new Path(new Options().executable).directoryPath | 143 sdkRoot = path.dirname(path.dirname(new Options().executable)); |
| 144 .directoryPath; | 144 logger.info('SDK Root: ${sdkRoot}'); |
| 145 logger.info("SDK Root: ${sdkRoot.toString()}"); | |
| 146 } | 145 } |
| 147 | 146 |
| 148 Path packageDir = libraries.last.directoryPath.append("packages"); | 147 getMirrorSystem(libraries, sdkRoot, packageRoot: packageDir) |
| 149 logger.info("Package Root: ${packageDir.toString()}"); | 148 .then((MirrorSystem mirrorSystem) { |
| 150 getMirrorSystem(libraries, sdkRoot, | |
| 151 packageRoot: packageDir).then((MirrorSystem mirrorSystem) { | |
| 152 if (mirrorSystem.libraries.values.isEmpty) { | 149 if (mirrorSystem.libraries.values.isEmpty) { |
| 153 throw new UnsupportedError("No Library Mirrors."); | 150 throw new UnsupportedError('No Library Mirrors.'); |
| 154 } | 151 } |
| 155 this.libraries = mirrorSystem.libraries.values; | 152 this.libraries = mirrorSystem.libraries.values; |
| 156 documentLibraries(); | 153 documentLibraries(); |
| 157 }); | 154 }); |
| 158 } | 155 } |
| 159 | 156 |
| 160 /** | 157 /** |
| 161 * Analyzes set of libraries and provides a mirror system which can be used | 158 * Analyzes set of libraries and provides a mirror system which can be used |
| 162 * for static inspection of the source code. | 159 * for static inspection of the source code. |
| 163 */ | 160 */ |
| 164 Future<MirrorSystem> getMirrorSystem(List<Path> libraries, | 161 Future<MirrorSystem> getMirrorSystem(List<String> libraries, |
| 165 Path libraryRoot, {Path packageRoot}) { | 162 String libraryRoot, {String packageRoot}) { |
|
Andrei Mouravski
2013/06/25 20:13:22
Don't forget to actually update libraryRoot to Pat
janicejl
2013/06/25 20:50:15
Should I still make it a Path if it works without
| |
| 166 SourceFileProvider provider = new SourceFileProvider(); | 163 SourceFileProvider provider = new SourceFileProvider(); |
| 167 api.DiagnosticHandler diagnosticHandler = | 164 api.DiagnosticHandler diagnosticHandler = |
| 168 new FormattingDiagnosticHandler(provider).diagnosticHandler; | 165 new FormattingDiagnosticHandler(provider).diagnosticHandler; |
| 169 Uri libraryUri = currentDirectory.resolve(appendSlash('$libraryRoot')); | 166 Uri libraryUri = currentDirectory.resolve(appendSlash('$libraryRoot')); |
| 170 Uri packageUri = null; | 167 Uri packageUri = null; |
| 171 if (packageRoot != null) { | 168 if (packageRoot != null) { |
| 172 packageUri = currentDirectory.resolve(appendSlash('$packageRoot')); | 169 packageUri = currentDirectory.resolve(appendSlash('$packageRoot')); |
| 173 } | 170 } |
| 174 List<Uri> librariesUri = <Uri>[]; | 171 List<Uri> librariesUri = <Uri>[]; |
| 175 libraries.forEach((library) { | 172 libraries.forEach((library) { |
| 176 librariesUri.add(currentDirectory.resolve(library.toString())); | 173 librariesUri.add(currentDirectory.resolve(library)); |
| 177 }); | 174 }); |
| 178 return dart2js.analyze(librariesUri, libraryUri, packageUri, | 175 return dart2js.analyze(librariesUri, libraryUri, packageUri, |
| 179 provider.readStringFromUri, diagnosticHandler, | 176 provider.readStringFromUri, diagnosticHandler, |
| 180 ['--preserve-comments', '--categories=Client,Server']); | 177 ['--preserve-comments', '--categories=Client,Server']); |
| 181 } | 178 } |
| 182 | 179 |
| 183 /** | 180 /** |
| 184 * Creates documentation for filtered libraries. | 181 * Creates documentation for filtered libraries. |
| 185 */ | 182 */ |
| 186 void documentLibraries() { | 183 void documentLibraries() { |
| 187 _libraries.forEach((library) { | 184 _libraries.forEach((library) { |
| 188 // Files belonging to the SDK have a uri that begins with "dart:". | 185 // Files belonging to the SDK have a uri that begins with 'dart:'. |
| 189 if (includeSdk || !library.uri.toString().startsWith("dart:")) { | 186 if (includeSdk || !library.uri.toString().startsWith('dart:')) { |
| 190 _currentLibrary = library; | 187 _currentLibrary = library; |
| 191 var result = new Library(library.qualifiedName, _getComment(library), | 188 var result = new Library(library.qualifiedName, _getComment(library), |
| 192 _getVariables(library.variables), _getMethods(library.functions), | 189 _getVariables(library.variables), _getMethods(library.functions), |
| 193 _getClasses(library.classes), nextID); | 190 _getClasses(library.classes)); |
| 194 if (outputToJson) { | 191 if (outputToJson) { |
| 195 _writeToFile(stringify(result.toMap()), "${result.name}.json"); | 192 _writeToFile(stringify(result.toMap()), '${result.name}.json'); |
| 196 } | 193 } |
| 197 if (outputToYaml) { | 194 if (outputToYaml) { |
| 198 _writeToFile(getYamlString(result.toMap()), "${result.name}.yaml"); | 195 _writeToFile(getYamlString(result.toMap()), '${result.name}.yaml'); |
| 199 } | 196 } |
| 200 } | 197 } |
| 201 }); | 198 }); |
| 202 } | 199 } |
| 203 | 200 |
| 204 /// Saves list of libraries for Docgen object. | 201 /// Saves list of libraries for Docgen object. |
| 205 void set libraries(value){ | 202 void set libraries(value){ |
| 206 _libraries = value; | 203 _libraries = value; |
| 207 } | 204 } |
| 208 | 205 |
| 209 /** | 206 /** |
| 210 * Returns any documentation comments associated with a mirror with | 207 * Returns any documentation comments associated with a mirror with |
| 211 * simple markdown converted to html. | 208 * simple markdown converted to html. |
| 212 */ | 209 */ |
| 213 String _getComment(DeclarationMirror mirror) { | 210 String _getComment(DeclarationMirror mirror) { |
| 214 String commentText; | 211 String commentText; |
| 215 mirror.metadata.forEach((metadata) { | 212 mirror.metadata.forEach((metadata) { |
| 216 if (metadata is CommentInstanceMirror) { | 213 if (metadata is CommentInstanceMirror) { |
| 217 CommentInstanceMirror comment = metadata; | 214 CommentInstanceMirror comment = metadata; |
| 218 if (comment.isDocComment) { | 215 if (comment.isDocComment) { |
| 219 if (commentText == null) { | 216 if (commentText == null) { |
| 220 commentText = comment.trimmedText; | 217 commentText = comment.trimmedText; |
| 221 } else { | 218 } else { |
| 222 commentText = "$commentText ${comment.trimmedText}"; | 219 commentText = '$commentText ${comment.trimmedText}'; |
| 223 } | 220 } |
| 224 } | 221 } |
| 225 } | 222 } |
| 226 }); | 223 }); |
| 227 commentText = commentText == null ? "" : | 224 commentText = commentText == null ? '' : |
| 228 markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver) | 225 markdown.markdownToHtml(commentText.trim(), linkResolver: linkResolver) |
| 229 .replaceAll("\n", ""); | 226 .replaceAll('\n', ''); |
| 230 return commentText; | 227 return commentText; |
| 231 } | 228 } |
| 232 | 229 |
| 233 /** | 230 /** |
| 234 * Converts all [_] references in comments to <code>_</code>. | 231 * Converts all [_] references in comments to <code>_</code>. |
| 235 */ | 232 */ |
| 236 // TODO(tmandel): Create proper links for [_] style markdown based | 233 // TODO(tmandel): Create proper links for [_] style markdown based |
| 237 // on scope once layout of viewer is finished. | 234 // on scope once layout of viewer is finished. |
| 238 markdown.Node fixReference(String name, LibraryMirror currentLibrary, | 235 markdown.Node fixReference(String name, LibraryMirror currentLibrary, |
| 239 ClassMirror currentClass, MemberMirror currentMember) { | 236 ClassMirror currentClass, MemberMirror currentMember) { |
| 240 return new markdown.Element.text('code', name); | 237 return new markdown.Element.text('code', name); |
| 241 } | 238 } |
| 242 | 239 |
| 243 /** | 240 /** |
| 244 * Returns a map of [Variable] objects constructed from inputted mirrors. | 241 * Returns a map of [Variable] objects constructed from inputted mirrors. |
| 245 */ | 242 */ |
| 246 Map<String, Variable> _getVariables(Map<String, VariableMirror> mirrorMap) { | 243 Map<String, Variable> _getVariables(Map<String, VariableMirror> mirrorMap) { |
| 247 var data = {}; | 244 var data = {}; |
| 248 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { | 245 mirrorMap.forEach((String mirrorName, VariableMirror mirror) { |
| 249 if (includePrivate || !mirror.isPrivate) { | 246 if (includePrivate || !mirror.isPrivate) { |
| 250 _currentMember = mirror; | 247 _currentMember = mirror; |
| 251 data[mirrorName] = new Variable(mirrorName, mirror.isFinal, | 248 data[mirrorName] = new Variable(mirrorName, mirror.qualifiedName, |
| 252 mirror.isStatic, mirror.type.toString(), _getComment(mirror), | 249 mirror.isFinal, mirror.isStatic, mirror.type.qualifiedName, |
| 253 nextID); | 250 _getComment(mirror)); |
| 254 } | 251 } |
| 255 }); | 252 }); |
| 256 return data; | 253 return data; |
| 257 } | 254 } |
| 258 | 255 |
| 259 /** | 256 /** |
| 260 * Returns a map of [Method] objects constructed from inputted mirrors. | 257 * Returns a map of [Method] objects constructed from inputted mirrors. |
| 261 */ | 258 */ |
| 262 Map<String, Method> _getMethods(Map<String, MethodMirror> mirrorMap) { | 259 Map<String, Method> _getMethods(Map<String, MethodMirror> mirrorMap) { |
| 263 var data = {}; | 260 var data = {}; |
| 264 mirrorMap.forEach((String mirrorName, MethodMirror mirror) { | 261 mirrorMap.forEach((String mirrorName, MethodMirror mirror) { |
| 265 if (includePrivate || !mirror.isPrivate) { | 262 if (includePrivate || !mirror.isPrivate) { |
| 266 _currentMember = mirror; | 263 _currentMember = mirror; |
| 267 data[mirrorName] = new Method(mirrorName, mirror.isSetter, | 264 data[mirrorName] = new Method(mirrorName, mirror.qualifiedName, |
| 268 mirror.isGetter, mirror.isConstructor, mirror.isOperator, | 265 mirror.isSetter, mirror.isGetter, mirror.isConstructor, |
| 269 mirror.isStatic, mirror.returnType.toString(), _getComment(mirror), | 266 mirror.isOperator, mirror.isStatic, mirror.returnType.qualifiedName, |
| 270 _getParameters(mirror.parameters), nextID); | 267 _getComment(mirror), _getParameters(mirror.parameters)); |
| 271 } | 268 } |
| 272 }); | 269 }); |
| 273 return data; | 270 return data; |
| 274 } | 271 } |
| 275 | 272 |
| 276 /** | 273 /** |
| 277 * Returns a map of [Class] objects constructed from inputted mirrors. | 274 * Returns a map of [Class] objects constructed from inputted mirrors. |
| 278 */ | 275 */ |
| 279 Map<String, Class> _getClasses(Map<String, ClassMirror> mirrorMap) { | 276 Map<String, Class> _getClasses(Map<String, ClassMirror> mirrorMap) { |
| 280 var data = {}; | 277 var data = {}; |
| 281 mirrorMap.forEach((String mirrorName, ClassMirror mirror) { | 278 mirrorMap.forEach((String mirrorName, ClassMirror mirror) { |
| 282 if (includePrivate || !mirror.isPrivate) { | 279 if (includePrivate || !mirror.isPrivate) { |
| 283 _currentClass = mirror; | 280 _currentClass = mirror; |
| 284 var superclass = (mirror.superclass != null) ? | 281 var superclass = (mirror.superclass != null) ? |
| 285 mirror.superclass.qualifiedName : ""; | 282 mirror.superclass.qualifiedName : ''; |
| 286 var interfaces = | 283 var interfaces = |
| 287 mirror.superinterfaces.map((interface) => interface.qualifiedName); | 284 mirror.superinterfaces.map((interface) => interface.qualifiedName); |
| 288 data[mirrorName] = new Class(mirrorName, superclass, mirror.isAbstract, | 285 data[mirrorName] = new Class(mirrorName, mirror.qualifiedName, |
| 289 mirror.isTypedef, _getComment(mirror), interfaces.toList(), | 286 superclass, mirror.isAbstract, mirror.isTypedef, |
| 290 _getVariables(mirror.variables), _getMethods(mirror.methods), | 287 _getComment(mirror), interfaces.toList(), |
| 291 nextID); | 288 _getVariables(mirror.variables), _getMethods(mirror.methods)); |
| 292 } | 289 } |
| 293 }); | 290 }); |
| 294 return data; | 291 return data; |
| 295 } | 292 } |
| 296 | 293 |
| 297 /** | 294 /** |
| 298 * Returns a map of [Parameter] objects constructed from inputted mirrors. | 295 * Returns a map of [Parameter] objects constructed from inputted mirrors. |
| 299 */ | 296 */ |
| 300 Map<String, Parameter> _getParameters(List<ParameterMirror> mirrorList) { | 297 Map<String, Parameter> _getParameters(List<ParameterMirror> mirrorList) { |
| 301 var data = {}; | 298 var data = {}; |
| 302 mirrorList.forEach((ParameterMirror mirror) { | 299 mirrorList.forEach((ParameterMirror mirror) { |
| 303 _currentMember = mirror; | 300 _currentMember = mirror; |
| 304 data[mirror.simpleName] = new Parameter(mirror.simpleName, | 301 data[mirror.simpleName] = new Parameter(mirror.simpleName, |
| 305 mirror.isOptional, mirror.isNamed, mirror.hasDefaultValue, | 302 mirror.qualifiedName, mirror.isOptional, mirror.isNamed, |
| 306 mirror.type.toString(), mirror.defaultValue, nextID); | 303 mirror.hasDefaultValue, mirror.type.qualifiedName, |
| 304 mirror.defaultValue); | |
| 307 }); | 305 }); |
| 308 return data; | 306 return data; |
| 309 } | 307 } |
| 310 } | 308 } |
| 311 | 309 |
| 312 /** | 310 /** |
| 313 * Transforms the map by calling toMap on each value in it. | 311 * Transforms the map by calling toMap on each value in it. |
| 314 */ | 312 */ |
| 315 Map recurseMap(Map inputMap) { | 313 Map recurseMap(Map inputMap) { |
| 316 var outputMap = {}; | 314 var outputMap = {}; |
| 317 inputMap.forEach((key, value) { | 315 inputMap.forEach((key, value) { |
| 318 outputMap[key] = value.toMap(); | 316 outputMap[key] = value.toMap(); |
| 319 }); | 317 }); |
| 320 return outputMap; | 318 return outputMap; |
| 321 } | 319 } |
| 322 | 320 |
| 323 /** | 321 /** |
| 324 * A class containing contents of a Dart library. | 322 * A class containing contents of a Dart library. |
| 325 */ | 323 */ |
| 326 class Library { | 324 class Library { |
| 327 | 325 |
| 328 /// Unique ID number for resolving links. | |
| 329 int id; | |
| 330 | |
| 331 /// Documentation comment with converted markdown. | 326 /// Documentation comment with converted markdown. |
| 332 String comment; | 327 String comment; |
| 333 | 328 |
| 334 /// Top-level variables in the library. | 329 /// Top-level variables in the library. |
| 335 Map<String, Variable> variables; | 330 Map<String, Variable> variables; |
| 336 | 331 |
| 337 /// Top-level functions in the library. | 332 /// Top-level functions in the library. |
| 338 Map<String, Method> functions; | 333 Map<String, Method> functions; |
| 339 | 334 |
| 340 /// Classes defined within the library | 335 /// Classes defined within the library |
| 341 Map<String, Class> classes; | 336 Map<String, Class> classes; |
| 342 | 337 |
| 343 String name; | 338 String name; |
| 344 | 339 |
| 345 Library(this.name, this.comment, this.variables, | 340 Library(this.name, this.comment, this.variables, |
| 346 this.functions, this.classes, this.id); | 341 this.functions, this.classes); |
| 347 | 342 |
| 348 /// Generates a map describing the [Library] object. | 343 /// Generates a map describing the [Library] object. |
| 349 Map toMap() { | 344 Map toMap() { |
| 350 var libraryMap = {}; | 345 var libraryMap = {}; |
| 351 libraryMap["id"] = id; | 346 libraryMap['name'] = name; |
| 352 libraryMap["name"] = name; | 347 libraryMap['comment'] = comment; |
| 353 libraryMap["comment"] = comment; | 348 libraryMap['variables'] = recurseMap(variables); |
| 354 libraryMap["variables"] = recurseMap(variables); | 349 libraryMap['functions'] = recurseMap(functions); |
| 355 libraryMap["functions"] = recurseMap(functions); | 350 libraryMap['classes'] = recurseMap(classes); |
| 356 libraryMap["classes"] = recurseMap(classes); | |
| 357 return libraryMap; | 351 return libraryMap; |
| 358 } | 352 } |
| 359 } | 353 } |
| 360 | 354 |
| 361 /** | 355 /** |
| 362 * A class containing contents of a Dart class. | 356 * A class containing contents of a Dart class. |
| 363 */ | 357 */ |
| 364 // TODO(tmandel): Figure out how to do typedefs (what is needed) | 358 // TODO(tmandel): Figure out how to do typedefs (what is needed) |
| 365 class Class { | 359 class Class { |
| 366 | 360 |
| 367 /// Unique ID number for resolving links. | |
| 368 int id; | |
| 369 | |
| 370 /// Documentation comment with converted markdown. | 361 /// Documentation comment with converted markdown. |
| 371 String comment; | 362 String comment; |
| 372 | 363 |
| 373 /// List of the names of interfaces that this class implements. | 364 /// List of the names of interfaces that this class implements. |
| 374 List<String> interfaces; | 365 List<String> interfaces; |
| 375 | 366 |
| 376 /// Top-level variables in the class. | 367 /// Top-level variables in the class. |
| 377 Map<String, Variable> variables; | 368 Map<String, Variable> variables; |
| 378 | 369 |
| 379 /// Methods in the class. | 370 /// Methods in the class. |
| 380 Map<String, Method> methods; | 371 Map<String, Method> methods; |
| 381 | 372 |
| 382 String name; | 373 String name; |
| 374 String qualifiedName; | |
| 383 String superclass; | 375 String superclass; |
| 384 bool isAbstract; | 376 bool isAbstract; |
| 385 bool isTypedef; | 377 bool isTypedef; |
| 386 | 378 |
| 387 Class(this.name, this.superclass, this.isAbstract, this.isTypedef, | 379 Class(this.name, this.qualifiedName, this.superclass, this.isAbstract, this.is Typedef, |
| 388 this.comment, this.interfaces, this.variables, this.methods, this.id); | 380 this.comment, this.interfaces, this.variables, this.methods); |
| 389 | 381 |
| 390 /// Generates a map describing the [Class] object. | 382 /// Generates a map describing the [Class] object. |
| 391 Map toMap() { | 383 Map toMap() { |
| 392 var classMap = {}; | 384 var classMap = {}; |
| 393 classMap["id"] = id; | 385 classMap['name'] = name; |
| 394 classMap["name"] = name; | 386 classMap['qualifiedname'] = qualifiedName; |
| 395 classMap["comment"] = comment; | 387 classMap['comment'] = comment; |
| 396 classMap["superclass"] = superclass; | 388 classMap['superclass'] = superclass; |
| 397 classMap["abstract"] = isAbstract.toString(); | 389 classMap['abstract'] = isAbstract.toString(); |
| 398 classMap["typedef"] = isTypedef.toString(); | 390 classMap['typedef'] = isTypedef.toString(); |
| 399 classMap["implements"] = new List.from(interfaces); | 391 classMap['implements'] = new List.from(interfaces); |
| 400 classMap["variables"] = recurseMap(variables); | 392 classMap['variables'] = recurseMap(variables); |
| 401 classMap["methods"] = recurseMap(methods); | 393 classMap['methods'] = recurseMap(methods); |
| 402 return classMap; | 394 return classMap; |
| 403 } | 395 } |
| 404 } | 396 } |
| 405 | 397 |
| 406 /** | 398 /** |
| 407 * A class containing properties of a Dart variable. | 399 * A class containing properties of a Dart variable. |
| 408 */ | 400 */ |
| 409 class Variable { | 401 class Variable { |
| 410 | 402 |
| 411 /// Unique ID number for resolving links. | |
| 412 int id; | |
| 413 | |
| 414 /// Documentation comment with converted markdown. | 403 /// Documentation comment with converted markdown. |
| 415 String comment; | 404 String comment; |
| 416 | 405 |
| 417 String name; | 406 String name; |
| 407 String qualifiedName; | |
| 418 bool isFinal; | 408 bool isFinal; |
| 419 bool isStatic; | 409 bool isStatic; |
| 420 String type; | 410 String type; |
| 421 | 411 |
| 422 Variable(this.name, this.isFinal, this.isStatic, this.type, | 412 Variable(this.name, this.qualifiedName, this.isFinal, this.isStatic, |
| 423 this.comment, this.id); | 413 this.type, this.comment); |
| 424 | 414 |
| 425 /// Generates a map describing the [Variable] object. | 415 /// Generates a map describing the [Variable] object. |
| 426 Map toMap() { | 416 Map toMap() { |
| 427 var variableMap = {}; | 417 var variableMap = {}; |
| 428 variableMap["id"] = id; | 418 variableMap['name'] = name; |
| 429 variableMap["name"] = name; | 419 variableMap['qualifiedname'] = qualifiedName; |
| 430 variableMap["comment"] = comment; | 420 variableMap['comment'] = comment; |
| 431 variableMap["final"] = isFinal.toString(); | 421 variableMap['final'] = isFinal.toString(); |
| 432 variableMap["static"] = isStatic.toString(); | 422 variableMap['static'] = isStatic.toString(); |
| 433 variableMap["type"] = type; | 423 variableMap['type'] = type; |
| 434 return variableMap; | 424 return variableMap; |
| 435 } | 425 } |
| 436 } | 426 } |
| 437 | 427 |
| 438 /** | 428 /** |
| 439 * A class containing properties of a Dart method. | 429 * A class containing properties of a Dart method. |
| 440 */ | 430 */ |
| 441 class Method { | 431 class Method { |
| 442 | 432 |
| 443 /// Unique ID number for resolving links. | |
| 444 int id; | |
| 445 | |
| 446 /// Documentation comment with converted markdown. | 433 /// Documentation comment with converted markdown. |
| 447 String comment; | 434 String comment; |
| 448 | 435 |
| 449 /// Parameters for this method. | 436 /// Parameters for this method. |
| 450 Map<String, Parameter> parameters; | 437 Map<String, Parameter> parameters; |
| 451 | 438 |
| 452 String name; | 439 String name; |
| 440 String qualifiedName; | |
| 453 bool isSetter; | 441 bool isSetter; |
| 454 bool isGetter; | 442 bool isGetter; |
| 455 bool isConstructor; | 443 bool isConstructor; |
| 456 bool isOperator; | 444 bool isOperator; |
| 457 bool isStatic; | 445 bool isStatic; |
| 458 String returnType; | 446 String returnType; |
| 459 | 447 |
| 460 Method(this.name, this.isSetter, this.isGetter, this.isConstructor, | 448 Method(this.name, this.qualifiedName, this.isSetter, this.isGetter, |
| 461 this.isOperator, this.isStatic, this.returnType, this.comment, | 449 this.isConstructor, this.isOperator, this.isStatic, this.returnType, |
| 462 this.parameters, this.id); | 450 this.comment, this.parameters); |
| 463 | 451 |
| 464 /// Generates a map describing the [Method] object. | 452 /// Generates a map describing the [Method] object. |
| 465 Map toMap() { | 453 Map toMap() { |
| 466 var methodMap = {}; | 454 var methodMap = {}; |
| 467 methodMap["id"] = id; | 455 methodMap['name'] = name; |
| 468 methodMap["name"] = name; | 456 methodMap['qualifiedname'] = qualifiedName; |
| 469 methodMap["comment"] = comment; | 457 methodMap['comment'] = comment; |
| 470 methodMap["type"] = isSetter ? "setter" : isGetter ? "getter" : | 458 methodMap['type'] = isSetter ? 'setter' : isGetter ? 'getter' : |
| 471 isOperator ? "operator" : isConstructor ? "constructor" : "method"; | 459 isOperator ? 'operator' : isConstructor ? 'constructor' : 'method'; |
| 472 methodMap["static"] = isStatic.toString(); | 460 methodMap['static'] = isStatic.toString(); |
| 473 methodMap["return"] = returnType; | 461 methodMap['return'] = returnType; |
| 474 methodMap["parameters"] = recurseMap(parameters); | 462 methodMap['parameters'] = recurseMap(parameters); |
| 475 return methodMap; | 463 return methodMap; |
| 476 } | 464 } |
| 477 } | 465 } |
| 478 | 466 |
| 479 /** | 467 /** |
| 480 * A class containing properties of a Dart method/function parameter. | 468 * A class containing properties of a Dart method/function parameter. |
| 481 */ | 469 */ |
| 482 class Parameter { | 470 class Parameter { |
| 483 | 471 |
| 484 /// Unique ID number for resolving links. | |
| 485 int id; | |
| 486 | |
| 487 String name; | 472 String name; |
| 473 String qualifiedName; | |
| 488 bool isOptional; | 474 bool isOptional; |
| 489 bool isNamed; | 475 bool isNamed; |
| 490 bool hasDefaultValue; | 476 bool hasDefaultValue; |
| 491 String type; | 477 String type; |
| 492 String defaultValue; | 478 String defaultValue; |
| 493 | 479 |
| 494 Parameter(this.name, this.isOptional, this.isNamed, this.hasDefaultValue, | 480 Parameter(this.name, this.qualifiedName, this.isOptional, this.isNamed, this.h asDefaultValue, |
| 495 this.type, this.defaultValue, this.id); | 481 this.type, this.defaultValue); |
| 496 | 482 |
| 497 /// Generates a map describing the [Parameter] object. | 483 /// Generates a map describing the [Parameter] object. |
| 498 Map toMap() { | 484 Map toMap() { |
| 499 var parameterMap = {}; | 485 var parameterMap = {}; |
| 500 parameterMap["id"] = id; | 486 parameterMap['name'] = name; |
| 501 parameterMap["name"] = name; | 487 parameterMap['qualifiedname'] = qualifiedName; |
| 502 parameterMap["optional"] = isOptional.toString(); | 488 parameterMap['optional'] = isOptional.toString(); |
| 503 parameterMap["named"] = isNamed.toString(); | 489 parameterMap['named'] = isNamed.toString(); |
| 504 parameterMap["default"] = hasDefaultValue.toString(); | 490 parameterMap['default'] = hasDefaultValue.toString(); |
| 505 parameterMap["type"] = type; | 491 parameterMap['type'] = type; |
| 506 parameterMap["value"] = defaultValue; | 492 parameterMap['value'] = defaultValue; |
| 507 return parameterMap; | 493 return parameterMap; |
| 508 } | 494 } |
| 509 } | 495 } |
| 510 | 496 |
| 511 /** | 497 /** |
| 512 * Writes text to a file in the 'docs' directory. | 498 * Writes text to a file in the 'docs' directory. |
| 513 */ | 499 */ |
| 514 void _writeToFile(String text, String filename) { | 500 void _writeToFile(String text, String filename) { |
| 515 Directory dir = new Directory('docs'); | 501 Directory dir = new Directory('docs'); |
| 516 if (!dir.existsSync()) { | 502 if (!dir.existsSync()) { |
| 517 dir.createSync(); | 503 dir.createSync(); |
| 518 } | 504 } |
| 519 File file = new File('docs/$filename'); | 505 File file = new File('docs/$filename'); |
| 520 if (!file.existsSync()) { | 506 if (!file.existsSync()) { |
| 521 file.createSync(); | 507 file.createSync(); |
| 522 } | 508 } |
| 523 file.openSync(); | 509 file.openSync(); |
| 524 file.writeAsString(text); | 510 file.writeAsString(text); |
| 525 } | 511 } |
| OLD | NEW |