Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library docgen.generator; | 5 library docgen.generator; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 import 'dart:convert'; | 9 import 'dart:convert'; |
| 10 import 'dart:io'; | 10 import 'dart:io'; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 52 /// Docgen constructor initializes the link resolver for markdown parsing. | 52 /// Docgen constructor initializes the link resolver for markdown parsing. |
| 53 /// Also initializes the command line arguments. | 53 /// Also initializes the command line arguments. |
| 54 /// | 54 /// |
| 55 /// [packageRoot] is the packages directory of the directory being analyzed. | 55 /// [packageRoot] is the packages directory of the directory being analyzed. |
| 56 /// If [includeSdk] is `true`, then any SDK libraries explicitly imported will | 56 /// If [includeSdk] is `true`, then any SDK libraries explicitly imported will |
| 57 /// also be documented. | 57 /// also be documented. |
| 58 /// If [parseSdk] is `true`, then all Dart SDK libraries will be documented. | 58 /// If [parseSdk] is `true`, then all Dart SDK libraries will be documented. |
| 59 /// This option is useful when only the SDK libraries are needed. | 59 /// This option is useful when only the SDK libraries are needed. |
| 60 /// | 60 /// |
| 61 /// Returned Future completes with true if document generation is successful. | 61 /// Returned Future completes with true if document generation is successful. |
| 62 Future<bool> generateDocumentation(List<String> files, {String packageRoot, bool | 62 Future<bool> generateDocumentation(List<String> files, {String packageRoot, |
| 63 outputToYaml: true, bool includePrivate: false, bool includeSdk: false, bool | 63 bool outputToYaml: true, bool includePrivate: false, bool includeSdk: false, |
| 64 parseSdk: false, String introFileName: '', out: | 64 bool parseSdk: false, String introFileName: '', |
| 65 DEFAULT_OUTPUT_DIRECTORY, List<String> excludeLibraries: const [], bool | 65 out: DEFAULT_OUTPUT_DIRECTORY, List<String> excludeLibraries: const [], bool |
| 66 includeDependentPackages: false, String startPage, String dartBinary, String | 66 includeDependentPackages: false, String startPage, String dartBinary, |
| 67 pubScript}) { | 67 String pubScript, bool indentJSON: false}) { |
| 68 _excluded = excludeLibraries; | 68 _excluded = excludeLibraries; |
| 69 _pubScript = pubScript; | 69 _pubScript = pubScript; |
| 70 _dartBinary = dartBinary; | 70 _dartBinary = dartBinary; |
| 71 | 71 |
| 72 logger.onRecord.listen((record) => print(record.message)); | 72 logger.onRecord.listen((record) => print(record.message)); |
| 73 | 73 |
| 74 _ensureOutputDirectory(out); | 74 _ensureOutputDirectory(out); |
| 75 var updatedPackageRoot = _obtainPackageRoot(packageRoot, parseSdk, files); | 75 var updatedPackageRoot = _obtainPackageRoot(packageRoot, parseSdk, files); |
| 76 | 76 |
| 77 var requestedLibraries = _findLibrariesToDocument(files, | 77 var requestedLibraries = _findLibrariesToDocument(files, |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 96 new Map.fromIterables(availableLibraries.map((each) => each.uri), | 96 new Map.fromIterables(availableLibraries.map((each) => each.uri), |
| 97 availableLibraries); | 97 availableLibraries); |
| 98 var librariesToDocument = requestedLibraries | 98 var librariesToDocument = requestedLibraries |
| 99 .map((each) { | 99 .map((each) { |
| 100 return availableLibrariesByPath | 100 return availableLibrariesByPath |
| 101 .putIfAbsent(each, () => throw "Missing library $each"); | 101 .putIfAbsent(each, () => throw "Missing library $each"); |
| 102 }).toList(); | 102 }).toList(); |
| 103 librariesToDocument.addAll((includeSdk || parseSdk) ? sdkLibraries : []); | 103 librariesToDocument.addAll((includeSdk || parseSdk) ? sdkLibraries : []); |
| 104 librariesToDocument.removeWhere((x) => _excluded.contains( | 104 librariesToDocument.removeWhere((x) => _excluded.contains( |
| 105 dart2js_util.nameOf(x))); | 105 dart2js_util.nameOf(x))); |
| 106 _documentLibraries(librariesToDocument, includeSdk: includeSdk, | 106 _documentLibraries(librariesToDocument, includeSdk, parseSdk, introFileName, |
| 107 parseSdk: parseSdk, introFileName: introFileName, startPage: startPage); | 107 startPage, indentJSON); |
| 108 return true; | 108 return true; |
| 109 }); | 109 }); |
| 110 } | 110 } |
| 111 | 111 |
| 112 | 112 |
| 113 /// Analyzes set of libraries by getting a mirror system and triggers the | 113 /// Analyzes set of libraries by getting a mirror system and triggers the |
| 114 /// documentation of the libraries. | 114 /// documentation of the libraries. |
| 115 Future<MirrorSystem> getMirrorSystem(List<Uri> libraries, | 115 Future<MirrorSystem> getMirrorSystem(List<Uri> libraries, |
| 116 bool includePrivate, {String packageRoot, bool parseSdk: false}) { | 116 bool includePrivate, {String packageRoot, bool parseSdk: false}) { |
| 117 if (libraries.isEmpty) throw new StateError('No Libraries.'); | 117 if (libraries.isEmpty) throw new StateError('No Libraries.'); |
| 118 | 118 |
| 119 includePrivateMembers = includePrivate; | 119 includePrivateMembers = includePrivate; |
| 120 | 120 |
| 121 // Finds the root of SDK library based off the location of docgen. | 121 // Finds the root of SDK library based off the location of docgen. |
| 122 // We have two different places to look, depending if we're in a development | 122 // We have two different places to look, depending if we're in a development |
| 123 // repo or in a built SDK, either sdk or dart-sdk respectively | 123 // repo or in a built SDK, either sdk or dart-sdk respectively |
| 124 var root = rootDirectory; | 124 var root = rootDirectory; |
| 125 var sdkRoot = path.normalize(path.absolute(path.join(root, 'sdk'))); | 125 var sdkRoot = path.normalize(path.absolute(path.join(root, 'sdk'))); |
| 126 if (!new Directory(sdkRoot).existsSync()) { | 126 if (!new Directory(sdkRoot).existsSync()) { |
| 127 sdkRoot = path.normalize(path.absolute(path.join(root, 'dart-sdk'))); | 127 sdkRoot = path.normalize(path.absolute(path.join(root, 'dart-sdk'))); |
| 128 } | 128 } |
| 129 logger.info('SDK Root: ${sdkRoot}'); | 129 logger.info('SDK Root: ${sdkRoot}'); |
| 130 return analyzeLibraries(libraries, sdkRoot, | 130 return analyzeLibraries(libraries, sdkRoot, |
| 131 packageRoot: packageRoot); | 131 packageRoot: packageRoot); |
| 132 } | 132 } |
| 133 | 133 |
| 134 /// Writes [text] to a file in the output directory. | 134 /// Writes [text] to a file in the output directory. |
| 135 void _writeToFile(String text, String filename) { | 135 void _writeToFile(String text, String filename) { |
| 136 if (text == null) return; | 136 if (text == null) return; |
| 137 Directory dir = new Directory(_outputDirectory); | 137 |
|
kevmoo
2014/04/14 21:37:49
This was a whole mountain of silly.
Emily Fortuna
2014/04/14 23:40:33
oy vey. thank you.
| |
| 138 if (!dir.existsSync()) { | 138 var filePath = path.join(_outputDirectory, filename); |
| 139 dir.createSync(); | 139 |
| 140 } | 140 var parentDir = new Directory(path.dirname(filePath)); |
| 141 if (path.split(filename).length > 1) { | 141 if (!parentDir.existsSync()) parentDir.createSync(recursive: true); |
| 142 var splitList = path.split(filename); | 142 |
| 143 for (int i = 0; i < splitList.length; i++) { | 143 new File(filePath) |
| 144 var level = splitList[i]; | 144 .writeAsStringSync(text, mode: FileMode.WRITE); |
| 145 } | |
| 146 for (var level in path.split(filename)) { | |
| 147 var subdir = new Directory(path.join(_outputDirectory, path.dirname( | |
| 148 filename))); | |
| 149 if (!subdir.existsSync()) { | |
| 150 subdir.createSync(); | |
| 151 } | |
| 152 } | |
| 153 } | |
| 154 File file = new File(path.join(_outputDirectory, filename)); | |
| 155 file.writeAsStringSync(text, mode: FileMode.WRITE); | |
| 156 } | 145 } |
| 157 | 146 |
| 158 /// Resolve all the links in the introductory comments for a given library or | 147 /// Resolve all the links in the introductory comments for a given library or |
| 159 /// package as specified by [filename]. | 148 /// package as specified by [filename]. |
| 160 String _readIntroductionFile(String fileName, bool includeSdk) { | 149 String _readIntroductionFile(String fileName, bool includeSdk) { |
| 161 var linkResolver = (name) => globalFixReference(name); | 150 var linkResolver = (name) => globalFixReference(name); |
| 162 var defaultText = includeSdk ? _DEFAULT_SDK_INTRODUCTION : ''; | 151 var defaultText = includeSdk ? _DEFAULT_SDK_INTRODUCTION : ''; |
| 163 var introText = defaultText; | 152 var introText = defaultText; |
| 164 if (fileName.isNotEmpty) { | 153 if (fileName.isNotEmpty) { |
| 165 var introFile = new File(fileName); | 154 var introFile = new File(fileName); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 179 return compare; | 168 return compare; |
| 180 } | 169 } |
| 181 | 170 |
| 182 if (a is Library) return -1; | 171 if (a is Library) return -1; |
| 183 if (b is Library) return 1; | 172 if (b is Library) return 1; |
| 184 | 173 |
| 185 return a.qualifiedName.compareTo(b.qualifiedName); | 174 return a.qualifiedName.compareTo(b.qualifiedName); |
| 186 } | 175 } |
| 187 | 176 |
| 188 /// Creates documentation for filtered libraries. | 177 /// Creates documentation for filtered libraries. |
| 189 void _documentLibraries(List<LibraryMirror> libs, {bool includeSdk: false, | 178 void _documentLibraries(List<LibraryMirror> libs, bool includeSdk, |
| 190 bool parseSdk: false, String introFileName: '', String startPage}) { | 179 bool parseSdk, String introFileName, String startPage, bool indentJson) { |
| 191 libs.forEach((lib) { | 180 libs.forEach((lib) { |
| 192 // Files belonging to the SDK have a uri that begins with 'dart:'. | 181 // Files belonging to the SDK have a uri that begins with 'dart:'. |
| 193 if (includeSdk || !lib.uri.toString().startsWith('dart:')) { | 182 if (includeSdk || !lib.uri.toString().startsWith('dart:')) { |
| 194 generateLibrary(lib); | 183 generateLibrary(lib); |
| 195 } | 184 } |
| 196 }); | 185 }); |
| 197 | 186 |
| 198 var filteredEntities = new SplayTreeSet<Indexable>(_indexableComparer); | 187 var filteredEntities = new SplayTreeSet<Indexable>(_indexableComparer); |
| 199 for (Map<String, Set<Indexable>> firstLevel in mirrorToDocgen.values) { | 188 for (Map<String, Set<Indexable>> firstLevel in mirrorToDocgen.values) { |
| 200 for (Set<Indexable> items in firstLevel.values) { | 189 for (Set<Indexable> items in firstLevel.values) { |
| 201 for (Indexable item in items) { | 190 for (Indexable item in items) { |
| 202 if (isFullChainVisible(item)) { | 191 if (isFullChainVisible(item)) { |
| 203 if (item is! Method || | 192 if (item is! Method || |
| 204 (item is Method && item.methodInheritedFrom == null)) { | 193 (item is Method && item.methodInheritedFrom == null)) { |
| 205 filteredEntities.add(item); | 194 filteredEntities.add(item); |
| 206 } | 195 } |
| 207 } | 196 } |
| 208 } | 197 } |
| 209 } | 198 } |
| 210 } | 199 } |
| 211 | 200 |
| 212 // Outputs a JSON file with all libraries and their preview comments. | 201 // Outputs a JSON file with all libraries and their preview comments. |
| 213 // This will help the viewer know what libraries are available to read in. | 202 // This will help the viewer know what libraries are available to read in. |
| 214 Map<String, dynamic> libraryMap = { | 203 Map<String, dynamic> libraryMap = { |
| 215 'libraries': filteredEntities.where((e) => e is Library).map((e) => | 204 'libraries': filteredEntities.where((e) => e is Library).map((e) => |
| 216 e.previewMap).toList(), | 205 e.previewMap).toList(), |
| 217 'introduction': _readIntroductionFile(introFileName, includeSdk), | 206 'introduction': _readIntroductionFile(introFileName, includeSdk), |
| 218 'filetype': 'json' | 207 'filetype': 'json' |
| 219 }; | 208 }; |
| 220 _writeOutputFiles(libraryMap, filteredEntities, startPage); | 209 |
| 210 var encoder = new JsonEncoder.withIndent(indentJson ? ' ' : null); | |
| 211 | |
| 212 _writeOutputFiles(libraryMap, filteredEntities, startPage, encoder); | |
| 221 } | 213 } |
| 222 | 214 |
| 223 /// Output all of the libraries and classes into json files for consumption by a | 215 /// Output all of the libraries and classes into json files for consumption by a |
| 224 /// viewer. | 216 /// viewer. |
| 225 void _writeOutputFiles(Map<String, dynamic> libraryMap, Iterable<Indexable> | 217 void _writeOutputFiles(Map<String, dynamic> libraryMap, Iterable<Indexable> |
| 226 filteredEntities, String startPage) { | 218 filteredEntities, String startPage, JsonEncoder encoder) { |
| 227 if (startPage != null) libraryMap['start-page'] = startPage; | 219 if (startPage != null) libraryMap['start-page'] = startPage; |
| 228 | 220 |
| 229 _writeToFile(JSON.encode(libraryMap), 'library_list.json'); | 221 _writeToFile(encoder.convert(libraryMap), 'library_list.json'); |
| 230 | 222 |
| 231 // Output libraries and classes to file after all information is generated. | 223 // Output libraries and classes to file after all information is generated. |
| 232 filteredEntities.where((e) => e is Class || e is Library).forEach((output) { | 224 filteredEntities.where((e) => e is Class || e is Library).forEach((output) { |
| 233 _writeIndexableToFile(output); | 225 _writeIndexableToFile(output, encoder); |
| 234 }); | 226 }); |
| 235 | 227 |
| 236 // Outputs all the qualified names documented with their type. | 228 // Outputs all the qualified names documented with their type. |
| 237 // This will help generate search results. | 229 // This will help generate search results. |
| 238 var sortedEntities = filteredEntities.map((e) => | 230 var sortedEntities = filteredEntities |
| 239 '${e.qualifiedName} ${e.typeName}').toList()..sort(); | 231 .map((e) => '${e.qualifiedName} ${e.typeName}') |
| 232 .toList(); | |
| 240 | 233 |
| 241 _writeToFile(sortedEntities.join('\n') + '\n', 'index.txt'); | 234 sortedEntities.sort(); |
| 235 | |
| 236 var buffer = new StringBuffer() | |
|
kevmoo
2014/04/14 21:37:49
Avoid creating a huge string, then another one jus
Emily Fortuna
2014/04/14 23:40:33
sgtm
| |
| 237 ..writeAll(sortedEntities, '\n') | |
| 238 ..write('\n'); | |
| 239 | |
| 240 _writeToFile(buffer.toString(), 'index.txt'); | |
| 241 | |
| 242 var index = new SplayTreeMap.fromIterable(filteredEntities, | 242 var index = new SplayTreeMap.fromIterable(filteredEntities, |
| 243 key: (e) => e.qualifiedName, value: (e) => e.typeName); | 243 key: (e) => e.qualifiedName, value: (e) => e.typeName); |
| 244 | 244 |
| 245 _writeToFile(JSON.encode(index), 'index.json'); | 245 _writeToFile(encoder.convert(index), 'index.json'); |
| 246 } | 246 } |
| 247 | 247 |
| 248 /// Helper method to serialize the given Indexable out to a file. | 248 /// Helper method to serialize the given Indexable out to a file. |
| 249 void _writeIndexableToFile(Indexable result) { | 249 void _writeIndexableToFile(Indexable result, JsonEncoder encoder) { |
| 250 var outputFile = result.fileName + '.json'; | 250 var outputFile = result.fileName + '.json'; |
| 251 var output = JSON.encode(result.toMap()); | 251 var output = encoder.convert(result.toMap()); |
| 252 _writeToFile(output, outputFile); | 252 _writeToFile(output, outputFile); |
| 253 } | 253 } |
| 254 | 254 |
| 255 /// Set the location of the ouput directory, and ensure that the location is | 255 /// Set the location of the ouput directory, and ensure that the location is |
| 256 /// available on the file system. | 256 /// available on the file system. |
| 257 void _ensureOutputDirectory(String outputDirectory) { | 257 void _ensureOutputDirectory(String outputDirectory) { |
| 258 _outputDirectory = outputDirectory; | 258 _outputDirectory = outputDirectory; |
| 259 var dir = new Directory(_outputDirectory); | 259 var dir = new Directory(_outputDirectory); |
| 260 if (dir.existsSync()) dir.deleteSync(recursive: true); | 260 if (dir.existsSync()) dir.deleteSync(recursive: true); |
| 261 } | 261 } |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 463 * [Samples](http://www.dartlang.org/samples/) | 463 * [Samples](http://www.dartlang.org/samples/) |
| 464 * [A Tour of the Dart Libraries](http://www.dartlang.org/docs/dart-up-and-runn ing/contents/ch03.html) | 464 * [A Tour of the Dart Libraries](http://www.dartlang.org/docs/dart-up-and-runn ing/contents/ch03.html) |
| 465 | 465 |
| 466 This API reference is automatically generated from the source code in the | 466 This API reference is automatically generated from the source code in the |
| 467 [Dart project](https://code.google.com/p/dart/). | 467 [Dart project](https://code.google.com/p/dart/). |
| 468 If you'd like to contribute to this documentation, see | 468 If you'd like to contribute to this documentation, see |
| 469 [Contributing](https://code.google.com/p/dart/wiki/Contributing) | 469 [Contributing](https://code.google.com/p/dart/wiki/Contributing) |
| 470 and | 470 and |
| 471 [Writing API Documentation](https://code.google.com/p/dart/wiki/WritingApiDocume ntation). | 471 [Writing API Documentation](https://code.google.com/p/dart/wiki/WritingApiDocume ntation). |
| 472 """; | 472 """; |
| OLD | NEW |