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