111 lines
3.2 KiB
Dart
111 lines
3.2 KiB
Dart
/// Runs the Check Docs workspace validation tool.
|
|
library;
|
|
|
|
import 'dart:io';
|
|
|
|
/// Generates Dart docs for each package with public libraries and fails on warnings.
|
|
Future<void> main(List<String> arguments) async {
|
|
final missingFileDocs = await _trackedDartFilesMissingFileDocs();
|
|
if (missingFileDocs.isNotEmpty) {
|
|
stderr.writeln('Dart files missing file-level Dartdoc library headers:');
|
|
for (final path in missingFileDocs) {
|
|
stderr.writeln('- $path');
|
|
}
|
|
}
|
|
|
|
final outputRoot = Directory(_join(_join('doc', 'api'), 'packages'));
|
|
if (await outputRoot.exists()) {
|
|
await outputRoot.delete(recursive: true);
|
|
}
|
|
await outputRoot.create(recursive: true);
|
|
|
|
final packages = Directory('packages')
|
|
.listSync()
|
|
.whereType<Directory>()
|
|
.where((directory) {
|
|
return File(_join(directory.path, 'pubspec.yaml')).existsSync() &&
|
|
Directory(_join(directory.path, 'lib')).existsSync();
|
|
}).toList(growable: false)
|
|
..sort((left, right) => left.path.compareTo(right.path));
|
|
|
|
var failed = missingFileDocs.isNotEmpty;
|
|
for (final package in packages) {
|
|
final outputPath = _join(outputRoot.absolute.path, _basename(package.path));
|
|
stdout.writeln('> dart doc --output $outputPath (${package.path})');
|
|
final result = await Process.run(
|
|
'dart',
|
|
<String>['doc', '--output', outputPath],
|
|
workingDirectory: package.path,
|
|
runInShell: Platform.isWindows,
|
|
);
|
|
final output = '${result.stdout}${result.stderr}';
|
|
stdout.write(output);
|
|
if (result.exitCode != 0 || _hasWarnings(output)) {
|
|
failed = true;
|
|
}
|
|
}
|
|
|
|
if (failed) {
|
|
stderr.writeln('Dart documentation gate failed.');
|
|
exitCode = 1;
|
|
}
|
|
}
|
|
|
|
Future<List<String>> _trackedDartFilesMissingFileDocs() async {
|
|
final result = await Process.run(
|
|
'git',
|
|
<String>['ls-files', '*.dart'],
|
|
runInShell: Platform.isWindows,
|
|
);
|
|
if (result.exitCode != 0) {
|
|
throw ProcessException(
|
|
'git',
|
|
<String>['ls-files', '*.dart'],
|
|
'Unable to list tracked Dart files.',
|
|
result.exitCode,
|
|
);
|
|
}
|
|
|
|
final paths = (result.stdout as String)
|
|
.split('\n')
|
|
.where((path) => path.trim().isNotEmpty)
|
|
.toList(growable: false)
|
|
..sort();
|
|
|
|
final missing = <String>[];
|
|
for (final path in paths) {
|
|
final file = File(path);
|
|
final contents = await file.readAsString();
|
|
if (_isGeneratedPart(path, contents)) {
|
|
continue;
|
|
}
|
|
if (!_hasFileLevelLibraryDocs(contents)) {
|
|
missing.add(path);
|
|
}
|
|
}
|
|
return missing;
|
|
}
|
|
|
|
bool _isGeneratedPart(String path, String contents) {
|
|
return path.endsWith('.g.dart') || contents.startsWith("part of '");
|
|
}
|
|
|
|
bool _hasFileLevelLibraryDocs(String contents) {
|
|
return RegExp(r'^\s*///[\s\S]*?\nlibrary;', multiLine: false)
|
|
.hasMatch(contents);
|
|
}
|
|
|
|
bool _hasWarnings(String output) {
|
|
return output.contains(' warning:') ||
|
|
RegExp(r'Found [1-9][0-9]* warnings').hasMatch(output);
|
|
}
|
|
|
|
String _join(String first, String second) {
|
|
final separator = Platform.pathSeparator;
|
|
return '$first$separator$second';
|
|
}
|
|
|
|
String _basename(String path) {
|
|
final normalized = path.replaceAll('\\', '/');
|
|
return normalized.substring(normalized.lastIndexOf('/') + 1);
|
|
}
|