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 | |
|
Andrei Mouravski
2013/06/25 18:37:41
You don't need this newline.
janicejl
2013/06/25 19:47:49
Done.
| |
| 16 library docgen; | 17 library docgen; |
| 17 | 18 |
| 18 import 'dart:io'; | 19 import 'dart:io'; |
| 19 import 'dart:json'; | 20 import 'dart:json'; |
| 20 import 'dart:async'; | 21 import 'dart:async'; |
| 21 | 22 |
| 22 import 'package:args/args.dart'; | 23 import 'package:args/args.dart'; |
| 23 import 'package:logging/logging.dart'; | 24 import 'package:logging/logging.dart'; |
| 24 import 'package:markdown/markdown.dart' as markdown; | 25 import 'package:markdown/markdown.dart' as markdown; |
| 26 import 'package:pathos/path.dart' as path; | |
| 25 | 27 |
| 26 import 'dart2yaml.dart'; | 28 import 'dart2yaml.dart'; |
| 29 import 'io.dart'; | |
| 27 import '../../../sdk/lib/_internal/compiler/compiler.dart' as api; | 30 import '../../../sdk/lib/_internal/compiler/compiler.dart' as api; |
| 28 import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart'; | 31 import '../../../sdk/lib/_internal/compiler/implementation/filenames.dart'; |
| 29 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirro r.dart' | 32 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirro r.dart' |
| 30 as dart2js; | 33 as dart2js; |
| 31 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart' ; | 34 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart' ; |
| 32 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util. dart'; | 35 import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util. dart'; |
| 33 import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider. dart'; | 36 import '../../../sdk/lib/_internal/compiler/implementation/source_file_provider. dart'; |
| 34 | 37 |
| 35 var logger = new Logger("Docgen"); | 38 var logger = new Logger("Docgen"); |
| 36 | 39 |
| 37 /// Counter used to provide unique IDs for each distinct item. | 40 /// Counter used to provide unique IDs for each distinct item. |
| 38 int _nextID = 0; | 41 int _nextID = 0; |
| 39 | 42 |
| 40 int get nextID => _nextID++; | 43 int get nextID => _nextID++; |
| 41 | 44 |
| 42 const String usage = "Usage: dart docgen.dart [OPTIONS] [fooDir/barFile]"; | 45 const String usage = "Usage: dart docgen.dart [OPTIONS] [fooDir/barFile]"; |
| 43 | 46 |
| 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 | |
| 78 /** | 47 /** |
| 79 * This class documents a list of libraries. | 48 * This class documents a list of libraries. |
| 80 */ | 49 */ |
| 81 class Docgen { | 50 class Docgen { |
| 82 | 51 |
| 83 /// Libraries to be documented. | 52 /// Libraries to be documented. |
| 84 List<LibraryMirror> _libraries; | 53 List<LibraryMirror> _libraries; |
| 85 | 54 |
| 86 /// Current library being documented to be used for comment links. | 55 /// Current library being documented to be used for comment links. |
| 87 LibraryMirror _currentLibrary; | 56 LibraryMirror _currentLibrary; |
| 88 | 57 |
| 89 /// Current class being documented to be used for comment links. | 58 /// Current class being documented to be used for comment links. |
| 90 ClassMirror _currentClass; | 59 ClassMirror _currentClass; |
| 91 | 60 |
| 92 /// Current member being documented to be used for comment links. | 61 /// Current member being documented to be used for comment links. |
| 93 MemberMirror _currentMember; | 62 MemberMirror _currentMember; |
| 94 | 63 |
| 95 /// Resolves reference links | 64 /// Resolves reference links |
| 96 markdown.Resolver linkResolver; | 65 markdown.Resolver linkResolver; |
| 97 | 66 |
| 67 /// Package Directory of | |
| 68 String packageDir; | |
| 69 | |
| 98 bool outputToYaml; | 70 bool outputToYaml; |
| 99 bool outputToJson; | 71 bool outputToJson; |
| 100 bool includePrivate; | 72 bool includePrivate; |
| 101 /// State for whether or not the SDK libraries should also be outputted. | 73 /// State for whether or not the SDK libraries should also be outputted. |
| 102 bool includeSdk; | 74 bool includeSdk; |
| 103 | 75 |
| 104 /** | 76 /** |
| 105 * Docgen constructor initializes the link resolver for markdown parsing. | 77 * Docgen constructor initializes the link resolver for markdown parsing. |
| 106 * Also initializes the command line arguments. | 78 * Also initializes the command line arguments. |
| 107 */ | 79 */ |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 118 throw new UnsupportedError("Cannot have contradictory output flags."); | 90 throw new UnsupportedError("Cannot have contradictory output flags."); |
| 119 } | 91 } |
| 120 outputToYaml = argResults["output-format"] == "yaml" ? true : false; | 92 outputToYaml = argResults["output-format"] == "yaml" ? true : false; |
| 121 } | 93 } |
| 122 outputToJson = !outputToYaml; | 94 outputToJson = !outputToYaml; |
| 123 includePrivate = argResults["include-private"]; | 95 includePrivate = argResults["include-private"]; |
| 124 includeSdk = argResults["include-sdk"]; | 96 includeSdk = argResults["include-sdk"]; |
| 125 | 97 |
| 126 this.linkResolver = (name) => | 98 this.linkResolver = (name) => |
| 127 fixReference(name, _currentLibrary, _currentClass, _currentMember); | 99 fixReference(name, _currentLibrary, _currentClass, _currentMember); |
| 100 | |
| 101 analyze(argResults.rest); | |
| 102 } | |
| 103 | |
| 104 List<String> listLibraries(List<String> args) { | |
| 105 if (args.length != 1) { | |
| 106 throw new UnsupportedError(usage); | |
| 107 } | |
| 108 var libraries = new List<String>(); | |
| 109 var type = FileSystemEntity.typeSync(args[0]); | |
| 110 | |
| 111 if (type == FileSystemEntityType.NOT_FOUND) { | |
| 112 throw new UnsupportedError("File does not exist. $usage"); | |
| 113 } else if (type == FileSystemEntityType.LINK) { | |
| 114 var files = listDir(resolveLink(args[0]), recursive: true); | |
| 115 libraries.addAll(files.where((f) => | |
| 116 f.endsWith(".dart") && !f.contains("/packages"))); | |
| 117 packageDir = files.firstWhere((f) => | |
| 118 f.endsWith("/pubspec.yaml"), orElse: () => ""); | |
| 119 packageDir = packageDir == "" ? | |
| 120 "" : path.dirname(packageDir) + "/packages"; | |
| 121 } else if (type == FileSystemEntityType.FILE) { | |
| 122 libraries.add(path.absolute(args[0])); | |
| 123 packageDir = ""; | |
| 124 } else if (type == FileSystemEntityType.DIRECTORY) { | |
| 125 var files = listDir(args[0], recursive: true); | |
| 126 libraries.addAll(files.where((f) => | |
| 127 f.endsWith(".dart") && !f.contains("/packages"))); | |
| 128 packageDir = files.firstWhere((f) => | |
| 129 f.endsWith("/pubspec.yaml"), orElse: () => ""); | |
| 130 packageDir = packageDir == "" ? | |
| 131 "" : path.dirname(packageDir) + "/packages"; | |
| 132 } | |
| 133 logger.info("Package Directory: $packageDir"); | |
| 134 libraries.forEach((lib) => logger.info("Added to libraries: $lib")); | |
| 135 return libraries; | |
| 128 } | 136 } |
| 129 | 137 |
| 130 /** | 138 /** |
| 131 * Analyzes set of libraries by getting a mirror system and triggers the | 139 * Analyzes set of libraries by getting a mirror system and triggers the |
| 132 * documentation of the libraries. | 140 * documentation of the libraries. |
| 133 */ | 141 */ |
| 134 void analyze(List<Path> libraries) { | 142 void analyze(List<String> args) { |
| 143 var libraries = listLibraries(args); | |
| 144 if (libraries.isEmpty) throw new UnsupportedError("No Libraries. "); | |
| 135 // DART_SDK should be set to the root of the SDK library. | 145 // DART_SDK should be set to the root of the SDK library. |
| 136 var sdkRoot = Platform.environment["DART_SDK"]; | 146 var sdkRoot = Platform.environment["DART_SDK"]; |
| 137 if (sdkRoot != null) { | 147 if (sdkRoot != null) { |
| 138 logger.info("Using DART_SDK to find SDK at $sdkRoot"); | 148 logger.info("Using DART_SDK to find SDK at $sdkRoot"); |
| 139 sdkRoot = new Path(sdkRoot); | |
| 140 } else { | 149 } else { |
| 141 // If DART_SDK is not defined in the environment, | 150 // If DART_SDK is not defined in the environment, |
| 142 // assuming the dart executable is from the Dart SDK folder inside bin. | 151 // assuming the dart executable is from the Dart SDK folder inside bin. |
| 143 sdkRoot = new Path(new Options().executable).directoryPath | 152 sdkRoot = path.dirname(path.dirname(new Options().executable)); |
| 144 .directoryPath; | 153 logger.info("SDK Root: ${sdkRoot}"); |
| 145 logger.info("SDK Root: ${sdkRoot.toString()}"); | |
| 146 } | 154 } |
| 147 | 155 |
| 148 Path packageDir = libraries.last.directoryPath.append("packages"); | 156 getMirrorSystem(libraries, new Path(sdkRoot), |
| 149 logger.info("Package Root: ${packageDir.toString()}"); | 157 packageRoot: new Path(packageDir)).then((MirrorSystem mirrorSystem) { |
| 150 getMirrorSystem(libraries, sdkRoot, | |
| 151 packageRoot: packageDir).then((MirrorSystem mirrorSystem) { | |
| 152 if (mirrorSystem.libraries.values.isEmpty) { | 158 if (mirrorSystem.libraries.values.isEmpty) { |
| 153 throw new UnsupportedError("No Library Mirrors."); | 159 throw new UnsupportedError("No Library Mirrors."); |
| 154 } | 160 } |
| 155 this.libraries = mirrorSystem.libraries.values; | 161 this.libraries = mirrorSystem.libraries.values; |
| 156 documentLibraries(); | 162 documentLibraries(); |
| 157 }); | 163 }); |
| 158 } | 164 } |
| 159 | 165 |
| 160 /** | 166 /** |
| 161 * Analyzes set of libraries and provides a mirror system which can be used | 167 * Analyzes set of libraries and provides a mirror system which can be used |
| 162 * for static inspection of the source code. | 168 * for static inspection of the source code. |
| 163 */ | 169 */ |
| 164 Future<MirrorSystem> getMirrorSystem(List<Path> libraries, | 170 Future<MirrorSystem> getMirrorSystem(List<String> libraries, |
| 165 Path libraryRoot, {Path packageRoot}) { | 171 Path libraryRoot, {Path packageRoot}) { |
| 166 SourceFileProvider provider = new SourceFileProvider(); | 172 SourceFileProvider provider = new SourceFileProvider(); |
| 167 api.DiagnosticHandler diagnosticHandler = | 173 api.DiagnosticHandler diagnosticHandler = |
| 168 new FormattingDiagnosticHandler(provider).diagnosticHandler; | 174 new FormattingDiagnosticHandler(provider).diagnosticHandler; |
| 169 Uri libraryUri = currentDirectory.resolve(appendSlash('$libraryRoot')); | 175 Uri libraryUri = currentDirectory.resolve(appendSlash('$libraryRoot')); |
| 170 Uri packageUri = null; | 176 Uri packageUri = null; |
| 171 if (packageRoot != null) { | 177 if (packageRoot != null) { |
| 172 packageUri = currentDirectory.resolve(appendSlash('$packageRoot')); | 178 packageUri = currentDirectory.resolve(appendSlash('$packageRoot')); |
| 173 } | 179 } |
| 174 List<Uri> librariesUri = <Uri>[]; | 180 List<Uri> librariesUri = <Uri>[]; |
| 175 libraries.forEach((library) { | 181 libraries.forEach((library) { |
| 176 librariesUri.add(currentDirectory.resolve(library.toString())); | 182 librariesUri.add(currentDirectory.resolve(library)); |
| 177 }); | 183 }); |
| 178 return dart2js.analyze(librariesUri, libraryUri, packageUri, | 184 return dart2js.analyze(librariesUri, libraryUri, packageUri, |
| 179 provider.readStringFromUri, diagnosticHandler, | 185 provider.readStringFromUri, diagnosticHandler, |
| 180 ['--preserve-comments', '--categories=Client,Server']); | 186 ['--preserve-comments', '--categories=Client,Server']); |
| 181 } | 187 } |
| 182 | 188 |
| 183 /** | 189 /** |
| 184 * Creates documentation for filtered libraries. | 190 * Creates documentation for filtered libraries. |
| 185 */ | 191 */ |
| 186 void documentLibraries() { | 192 void documentLibraries() { |
| 187 _libraries.forEach((library) { | 193 _libraries.forEach((library) { |
| 188 // Files belonging to the SDK have a uri that begins with "dart:". | 194 // Files belonging to the SDK have a uri that begins with "dart:". |
| 189 if (includeSdk || !library.uri.toString().startsWith("dart:")) { | 195 if (includeSdk || !library.uri.toString().startsWith("dart:")) { |
| 190 _currentLibrary = library; | 196 _currentLibrary = library; |
| 191 var result = new Library(library.qualifiedName, _getComment(library), | 197 var result = new Library(library.qualifiedName, _getComment(library), |
| 192 _getVariables(library.variables), _getMethods(library.functions), | 198 _getVariables(library.variables), _getMethods(library.functions), |
| 193 _getClasses(library.classes), nextID); | 199 _getClasses(library.classes), nextID); |
| 194 if (outputToJson) { | 200 if (outputToJson) { |
| 195 _writeToFile(stringify(result.toMap()), "${result.name}.json"); | 201 _writeToFile(stringify(result.toMap()), "${result.name}.json"); |
| 196 } | 202 } |
| 197 if (outputToYaml) { | 203 if (outputToYaml) { |
| 198 _writeToFile(getYamlString(result.toMap()), "${result.name}.yaml"); | 204 _writeToFile(getYamlString(result.toMap()), "${result.name}.yaml"); |
| 199 } | 205 } |
| 200 } | 206 } |
| 201 }); | 207 }); |
| 202 } | 208 } |
| 203 | 209 |
| 204 /// Saves list of libraries for Docgen object. | 210 /// Saves list of libraries for Docgen object. |
| 205 void set libraries(value){ | 211 void set libraries(value){ |
| 206 _libraries = value; | 212 _libraries = value; |
| 207 } | 213 } |
| 208 | 214 |
| 209 /** | 215 /** |
| 210 * Returns any documentation comments associated with a mirror with | 216 * Returns any documentation comments associated with a mirror with |
| 211 * simple markdown converted to html. | 217 * simple markdown converted to html. |
| 212 */ | 218 */ |
| 213 String _getComment(DeclarationMirror mirror) { | 219 String _getComment(DeclarationMirror mirror) { |
| 214 String commentText; | 220 String commentText; |
| 215 mirror.metadata.forEach((metadata) { | 221 mirror.metadata.forEach((metadata) { |
| 216 if (metadata is CommentInstanceMirror) { | 222 if (metadata is CommentInstanceMirror) { |
| 217 CommentInstanceMirror comment = metadata; | 223 CommentInstanceMirror comment = metadata; |
| 218 if (comment.isDocComment) { | 224 if (comment.isDocComment) { |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 516 if (!dir.existsSync()) { | 522 if (!dir.existsSync()) { |
| 517 dir.createSync(); | 523 dir.createSync(); |
| 518 } | 524 } |
| 519 File file = new File('docs/$filename'); | 525 File file = new File('docs/$filename'); |
| 520 if (!file.existsSync()) { | 526 if (!file.existsSync()) { |
| 521 file.createSync(); | 527 file.createSync(); |
| 522 } | 528 } |
| 523 file.openSync(); | 529 file.openSync(); |
| 524 file.writeAsString(text); | 530 file.writeAsString(text); |
| 525 } | 531 } |
| OLD | NEW |