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 /// **docgen** is a tool for creating machine readable representations of Dart | 5 /// **docgen** is a tool for creating machine readable representations of Dart |
6 /// code metadata, including: classes, members, comments and annotations. | 6 /// code metadata, including: classes, members, comments and annotations. |
7 /// | 7 /// |
8 /// docgen is run on a `.dart` file or a directory containing `.dart` files. | 8 /// docgen is run on a `.dart` file or a directory containing `.dart` files. |
9 /// | 9 /// |
10 /// $ dart docgen.dart [OPTIONS] [FILE/DIR] | 10 /// $ dart docgen.dart [OPTIONS] [FILE/DIR] |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 """; | 99 """; |
100 | 100 |
101 /// Docgen constructor initializes the link resolver for markdown parsing. | 101 /// Docgen constructor initializes the link resolver for markdown parsing. |
102 /// Also initializes the command line arguments. | 102 /// Also initializes the command line arguments. |
103 /// | 103 /// |
104 /// [packageRoot] is the packages directory of the directory being analyzed. | 104 /// [packageRoot] is the packages directory of the directory being analyzed. |
105 /// If [includeSdk] is `true`, then any SDK libraries explicitly imported will | 105 /// If [includeSdk] is `true`, then any SDK libraries explicitly imported will |
106 /// also be documented. | 106 /// also be documented. |
107 /// If [parseSdk] is `true`, then all Dart SDK libraries will be documented. | 107 /// If [parseSdk] is `true`, then all Dart SDK libraries will be documented. |
108 /// This option is useful when only the SDK libraries are needed. | 108 /// This option is useful when only the SDK libraries are needed. |
| 109 /// If [compile] is `true`, then after generating the documents, compile the |
| 110 /// viewer with dart2js. |
109 /// If [serve] is `true`, then after generating the documents we fire up a | 111 /// If [serve] is `true`, then after generating the documents we fire up a |
110 /// simple server to view the documentation. | 112 /// simple server to view the documentation. |
111 /// | 113 /// |
112 /// Returned Future completes with true if document generation is successful. | 114 /// Returned Future completes with true if document generation is successful. |
113 Future<bool> docgen(List<String> files, {String packageRoot, | 115 Future<bool> docgen(List<String> files, {String packageRoot, |
114 bool outputToYaml: true, bool includePrivate: false, bool includeSdk: false, | 116 bool outputToYaml: true, bool includePrivate: false, bool includeSdk: false, |
115 bool parseSdk: false, bool append: false, String introFileName: '', | 117 bool parseSdk: false, bool append: false, String introFileName: '', |
116 out: _DEFAULT_OUTPUT_DIRECTORY, List<String> excludeLibraries : const [], | 118 out: _DEFAULT_OUTPUT_DIRECTORY, List<String> excludeLibraries : const [], |
117 bool includeDependentPackages: false, bool serve: false, | 119 bool includeDependentPackages: false, bool compile: false, bool serve: false
, |
118 bool noDocs: false, String startPage}) { | 120 bool noDocs: false, String startPage, |
| 121 String pubScript, String dartBinary}) { |
119 var result; | 122 var result; |
120 if (!noDocs) { | 123 if (!noDocs) { |
121 _Viewer.ensureMovedViewerCode(); | 124 _Viewer.ensureMovedViewerCode(); |
122 result = _Generator.generateDocumentation(files, packageRoot: packageRoot, | 125 result = _Generator.generateDocumentation(files, packageRoot: packageRoot, |
123 outputToYaml: outputToYaml, includePrivate: includePrivate, | 126 outputToYaml: outputToYaml, includePrivate: includePrivate, |
124 includeSdk: includeSdk, parseSdk: parseSdk, append: append, | 127 includeSdk: includeSdk, parseSdk: parseSdk, append: append, |
125 introFileName: introFileName, out: out, | 128 introFileName: introFileName, out: out, |
126 excludeLibraries: excludeLibraries, | 129 excludeLibraries: excludeLibraries, |
127 includeDependentPackages: includeDependentPackages, | 130 includeDependentPackages: includeDependentPackages, |
128 startPage: startPage); | 131 startPage: startPage, pubScript: pubScript, dartBinary: dartBinary); |
129 _Viewer.addBackViewerCode(); | 132 _Viewer.addBackViewerCode(); |
130 if (serve) { | 133 if (compile || serve) { |
131 result.then((success) { | 134 result.then((success) { |
132 if (success) { | 135 if (success) { |
133 _Viewer._cloneAndServe(); | 136 _createViewer(serve); |
134 } | 137 } |
135 }); | 138 }); |
136 } | 139 } |
137 } else if (serve) { | 140 } else if (compile || serve) { |
138 _Viewer._cloneAndServe(); | 141 _createViewer(serve); |
139 } | 142 } |
140 return result; | 143 return result; |
141 } | 144 } |
142 | 145 |
| 146 void _createViewer(bool serve) { |
| 147 _Viewer._clone(); |
| 148 _Viewer._compile(); |
| 149 if (serve) { |
| 150 _Viewer._runServer(); |
| 151 } |
| 152 } |
| 153 |
143 /// Analyzes set of libraries by getting a mirror system and triggers the | 154 /// Analyzes set of libraries by getting a mirror system and triggers the |
144 /// documentation of the libraries. | 155 /// documentation of the libraries. |
145 Future<MirrorSystem> getMirrorSystem(List<Uri> libraries, | 156 Future<MirrorSystem> getMirrorSystem(List<Uri> libraries, |
146 {String packageRoot, bool parseSdk: false}) { | 157 {String packageRoot, bool parseSdk: false}) { |
147 if (libraries.isEmpty) throw new StateError('No Libraries.'); | 158 if (libraries.isEmpty) throw new StateError('No Libraries.'); |
148 | 159 |
149 // Finds the root of SDK library based off the location of docgen. | 160 // Finds the root of SDK library based off the location of docgen. |
150 // We have two different places to look, depending if we're in a development | 161 // We have two different places to look, depending if we're in a development |
151 // repo or in a built SDK, either sdk or dart-sdk respectively | 162 // repo or in a built SDK, either sdk or dart-sdk respectively |
152 var root = _Generator._rootDirectory; | 163 var root = _Generator._rootDirectory; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 | 251 |
241 /// This is set from the command line arguments flag --include-private | 252 /// This is set from the command line arguments flag --include-private |
242 static bool _includePrivate = false; | 253 static bool _includePrivate = false; |
243 | 254 |
244 /// Library names to explicitly exclude. | 255 /// Library names to explicitly exclude. |
245 /// | 256 /// |
246 /// Set from the command line option | 257 /// Set from the command line option |
247 /// --exclude-lib. | 258 /// --exclude-lib. |
248 static List<String> _excluded; | 259 static List<String> _excluded; |
249 | 260 |
| 261 /// The path of the pub script. |
| 262 static String _pubScript; |
| 263 |
| 264 /// The path of Dart binary. |
| 265 static String _dartBinary; |
| 266 |
250 /// Logger for printing out progress of documentation generation. | 267 /// Logger for printing out progress of documentation generation. |
251 static Logger logger = new Logger('Docgen'); | 268 static Logger logger = new Logger('Docgen'); |
252 | 269 |
253 /// Docgen constructor initializes the link resolver for markdown parsing. | 270 /// Docgen constructor initializes the link resolver for markdown parsing. |
254 /// Also initializes the command line arguments. | 271 /// Also initializes the command line arguments. |
255 /// | 272 /// |
256 /// [packageRoot] is the packages directory of the directory being analyzed. | 273 /// [packageRoot] is the packages directory of the directory being analyzed. |
257 /// If [includeSdk] is `true`, then any SDK libraries explicitly imported will | 274 /// If [includeSdk] is `true`, then any SDK libraries explicitly imported will |
258 /// also be documented. | 275 /// also be documented. |
259 /// If [parseSdk] is `true`, then all Dart SDK libraries will be documented. | 276 /// If [parseSdk] is `true`, then all Dart SDK libraries will be documented. |
260 /// This option is useful when only the SDK libraries are needed. | 277 /// This option is useful when only the SDK libraries are needed. |
261 /// | 278 /// |
262 /// Returned Future completes with true if document generation is successful. | 279 /// Returned Future completes with true if document generation is successful. |
263 static Future<bool> generateDocumentation(List<String> files, | 280 static Future<bool> generateDocumentation(List<String> files, |
264 {String packageRoot, bool outputToYaml: true, bool includePrivate: false, | 281 {String packageRoot, bool outputToYaml: true, bool includePrivate: false, |
265 bool includeSdk: false, bool parseSdk: false, bool append: false, | 282 bool includeSdk: false, bool parseSdk: false, bool append: false, |
266 String introFileName: '', out: _DEFAULT_OUTPUT_DIRECTORY, | 283 String introFileName: '', out: _DEFAULT_OUTPUT_DIRECTORY, |
267 List<String> excludeLibraries : const [], | 284 List<String> excludeLibraries : const [], |
268 bool includeDependentPackages: false, String startPage}) { | 285 bool includeDependentPackages: false, String startPage, |
| 286 String dartBinary, String pubScript}) { |
269 _excluded = excludeLibraries; | 287 _excluded = excludeLibraries; |
270 _includePrivate = includePrivate; | 288 _includePrivate = includePrivate; |
| 289 _pubScript = pubScript; |
| 290 _dartBinary = dartBinary; |
| 291 |
271 logger.onRecord.listen((record) => print(record.message)); | 292 logger.onRecord.listen((record) => print(record.message)); |
272 | 293 |
273 _ensureOutputDirectory(out, append); | 294 _ensureOutputDirectory(out, append); |
274 var updatedPackageRoot = _obtainPackageRoot(packageRoot, parseSdk, files); | 295 var updatedPackageRoot = _obtainPackageRoot(packageRoot, parseSdk, files); |
275 | 296 |
276 var requestedLibraries = _findLibrariesToDocument(files, | 297 var requestedLibraries = _findLibrariesToDocument(files, |
277 includeDependentPackages); | 298 includeDependentPackages); |
278 | 299 |
279 var allLibraries = []..addAll(requestedLibraries); | 300 var allLibraries = []..addAll(requestedLibraries); |
280 if (includeSdk) { | 301 if (includeSdk) { |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
588 } | 609 } |
589 }); | 610 }); |
590 return libraries; | 611 return libraries; |
591 } | 612 } |
592 | 613 |
593 /// All of the directories for our dependent packages | 614 /// All of the directories for our dependent packages |
594 /// If this is not a package, return an empty list. | 615 /// If this is not a package, return an empty list. |
595 static List<String> _allDependentPackageDirs(String packageDirectory) { | 616 static List<String> _allDependentPackageDirs(String packageDirectory) { |
596 var packageName = Library.packageNameFor(packageDirectory); | 617 var packageName = Library.packageNameFor(packageDirectory); |
597 if (packageName == '') return []; | 618 if (packageName == '') return []; |
598 var dependentsJson = Process.runSync('pub', ['list-package-dirs'], | 619 var dependentsJson = Process.runSync(_pubScript, ['list-package-dirs'], |
599 workingDirectory: packageDirectory, runInShell: true); | 620 workingDirectory: packageDirectory, runInShell: true); |
600 if (dependentsJson.exitCode != 0) { | 621 if (dependentsJson.exitCode != 0) { |
601 print(dependentsJson.stderr); | 622 print(dependentsJson.stderr); |
602 } | 623 } |
603 var dependents = JSON.decode(dependentsJson.stdout)['packages']; | 624 var dependents = JSON.decode(dependentsJson.stdout)['packages']; |
604 return dependents.values.toList(); | 625 return dependents.values.toList(); |
605 } | 626 } |
606 | 627 |
607 /// For all the libraries, return a list of the libraries that are part of | 628 /// For all the libraries, return a list of the libraries that are part of |
608 /// the SDK. | 629 /// the SDK. |
(...skipping 23 matching lines...) Expand all Loading... |
632 } | 653 } |
633 } | 654 } |
634 | 655 |
635 /// Convenience methods wrapped up in a class to pull down the docgen viewer for | 656 /// Convenience methods wrapped up in a class to pull down the docgen viewer for |
636 /// a viewable website, and start up a server for viewing. | 657 /// a viewable website, and start up a server for viewing. |
637 class _Viewer { | 658 class _Viewer { |
638 static String _dartdocViewerString = path.join(Directory.current.path, | 659 static String _dartdocViewerString = path.join(Directory.current.path, |
639 'dartdoc-viewer'); | 660 'dartdoc-viewer'); |
640 static Directory _dartdocViewerDir = new Directory(_dartdocViewerString); | 661 static Directory _dartdocViewerDir = new Directory(_dartdocViewerString); |
641 static Directory _topLevelTempDir; | 662 static Directory _topLevelTempDir; |
| 663 static Directory _webDocsDir; |
642 static bool movedViewerCode = false; | 664 static bool movedViewerCode = false; |
643 | 665 |
644 /// If our dartdoc-viewer code is already checked out, move it to a temporary | 666 /// If our dartdoc-viewer code is already checked out, move it to a temporary |
645 /// directory outside of the package directory, so we don't try to process it | 667 /// directory outside of the package directory, so we don't try to process it |
646 /// for documentation. | 668 /// for documentation. |
647 static void ensureMovedViewerCode() { | 669 static void ensureMovedViewerCode() { |
648 // TODO(efortuna): This will need to be modified to run on anyone's package | 670 // TODO(efortuna): This will need to be modified to run on anyone's package |
649 // outside of the checkout! | 671 // outside of the checkout! |
650 if (_dartdocViewerDir.existsSync()) { | 672 if (_dartdocViewerDir.existsSync()) { |
651 _topLevelTempDir = new Directory( | 673 _topLevelTempDir = new Directory( |
652 _Generator._rootDirectory).createTempSync(); | 674 _Generator._rootDirectory).createTempSync(); |
653 _dartdocViewerDir.renameSync(_topLevelTempDir.path); | 675 _dartdocViewerDir.renameSync(_topLevelTempDir.path); |
654 } | 676 } |
655 } | 677 } |
656 | 678 |
657 /// Move the dartdoc-viewer code back into place for "webpage deployment." | 679 /// Move the dartdoc-viewer code back into place for "webpage deployment." |
658 static void addBackViewerCode() { | 680 static void addBackViewerCode() { |
659 if (movedViewerCode) _dartdocViewerDir.renameSync(_dartdocViewerString); | 681 if (movedViewerCode) _dartdocViewerDir.renameSync(_dartdocViewerString); |
660 } | 682 } |
661 | 683 |
662 /// Serve up our generated documentation for viewing in a browser. | 684 /// Serve up our generated documentation for viewing in a browser. |
663 static void _cloneAndServe() { | 685 static void _clone() { |
664 // If the viewer code is already there, then don't clone again. | 686 // If the viewer code is already there, then don't clone again. |
665 if (_dartdocViewerDir.existsSync()) { | 687 if (_dartdocViewerDir.existsSync()) { |
666 _moveDirectoryAndServe(); | 688 _moveDirectoryAndServe(); |
667 } | 689 } |
668 else { | 690 else { |
669 var processResult = Process.runSync('git', ['clone', '-b', 'master', | 691 var processResult = Process.runSync('git', ['clone', '-b', 'master', |
670 'git://github.com/dart-lang/dartdoc-viewer.git'], | 692 'git://github.com/dart-lang/dartdoc-viewer.git'], |
671 runInShell: true); | 693 runInShell: true); |
672 | 694 |
673 if (processResult.exitCode == 0) { | 695 if (processResult.exitCode == 0) { |
674 _moveDirectoryAndServe(); | 696 /// Move the generated json/yaml docs directory to the dartdoc-viewer |
| 697 /// directory, to run as a webpage. |
| 698 var processResult = Process.runSync(_Generator._pubScript, |
| 699 ['upgrade'], runInShell: true, |
| 700 workingDirectory: path.join(_dartdocViewerDir.path, 'client')); |
| 701 print('process output: ${processResult.stdout}'); |
| 702 print('process stderr: ${processResult.stderr}'); |
| 703 |
| 704 var dir = new Directory(_Generator._outputDirectory == null? 'docs' : |
| 705 _Generator._outputDirectory); |
| 706 _webDocsDir = new Directory(path.join(_dartdocViewerDir.path, 'client', |
| 707 'web', 'docs')); |
| 708 if (dir.existsSync()) { |
| 709 // Move the docs folder to dartdoc-viewer/client/web/docs |
| 710 dir.renameSync(_webDocsDir.path); |
| 711 } |
675 } else { | 712 } else { |
676 print('Error cloning git repository:'); | 713 print('Error cloning git repository:'); |
677 print('process output: ${processResult.stdout}'); | 714 print('process output: ${processResult.stdout}'); |
678 print('process stderr: ${processResult.stderr}'); | 715 print('process stderr: ${processResult.stderr}'); |
679 } | 716 } |
680 } | 717 } |
681 } | 718 } |
682 | 719 |
683 /// Move the generated json/yaml docs directory to the dartdoc-viewer | 720 static void _compile() { |
684 /// directory, to run as a webpage. | 721 if (_webDocsDir.existsSync()) { |
685 static void _moveDirectoryAndServe() { | |
686 var processResult = Process.runSync('pub', ['update'], runInShell: true, | |
687 workingDirectory: path.join(_dartdocViewerDir.path, 'client')); | |
688 print('process output: ${processResult.stdout}'); | |
689 print('process stderr: ${processResult.stderr}'); | |
690 | |
691 var dir = new Directory(_Generator._outputDirectory == null? 'docs' : | |
692 _Generator._outputDirectory); | |
693 var webDocsDir = new Directory(path.join(_dartdocViewerDir.path, 'client', | |
694 'web', 'docs')); | |
695 if (dir.existsSync()) { | |
696 // Move the docs folder to dartdoc-viewer/client/web/docs | |
697 dir.renameSync(webDocsDir.path); | |
698 } | |
699 | |
700 if (webDocsDir.existsSync()) { | |
701 // Compile the code to JavaScript so we can run on any browser. | 722 // Compile the code to JavaScript so we can run on any browser. |
702 print('Compile app to JavaScript for viewing.'); | 723 print('Compile app to JavaScript for viewing.'); |
703 var processResult = Process.runSync('dart', ['deploy.dart'], | 724 var processResult = Process.runSync(_Generator._dartBinary, |
704 workingDirectory : path.join(_dartdocViewerDir.path, 'client'), | 725 ['deploy.dart'], workingDirectory : path.join(_dartdocViewerDir.path, |
705 runInShell: true); | 726 'client'), runInShell: true); |
706 print('process output: ${processResult.stdout}'); | 727 print('process output: ${processResult.stdout}'); |
707 print('process stderr: ${processResult.stderr}'); | 728 print('process stderr: ${processResult.stderr}'); |
708 _runServer(); | 729 var outputDir = path.join(_dartdocViewerDir.path, 'client', 'out', 'web'); |
| 730 print('Docs are available at $outputDir'); |
709 } | 731 } |
710 } | 732 } |
711 | 733 |
712 /// A simple HTTP server. Implemented here because this is part of the SDK, | 734 /// A simple HTTP server. Implemented here because this is part of the SDK, |
713 /// so it shouldn't have any external dependencies. | 735 /// so it shouldn't have any external dependencies. |
714 static void _runServer() { | 736 static void _runServer() { |
715 // Launch a server to serve out of the directory dartdoc-viewer/client/web. | 737 // Launch a server to serve out of the directory dartdoc-viewer/client/web. |
716 HttpServer.bind('localhost', 8080).then((HttpServer httpServer) { | 738 HttpServer.bind('localhost', 8080).then((HttpServer httpServer) { |
717 print('Server launched. Navigate your browser to: ' | 739 print('Server launched. Navigate your browser to: ' |
718 'http://localhost:${httpServer.port}'); | 740 'http://localhost:${httpServer.port}'); |
(...skipping 1455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2174 .map((e) => originalMirror.getField(e.simpleName).reflectee) | 2196 .map((e) => originalMirror.getField(e.simpleName).reflectee) |
2175 .where((e) => e != null) | 2197 .where((e) => e != null) |
2176 .toList(); | 2198 .toList(); |
2177 } | 2199 } |
2178 | 2200 |
2179 Map toMap() => { | 2201 Map toMap() => { |
2180 'name': Indexable.getDocgenObject(mirror, owningLibrary).docName, | 2202 'name': Indexable.getDocgenObject(mirror, owningLibrary).docName, |
2181 'parameters': parameters | 2203 'parameters': parameters |
2182 }; | 2204 }; |
2183 } | 2205 } |
OLD | NEW |