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