in tool/catalog/generate_widget_catalog.dart [19:108]
Future<void> main(List<String> args) async {
if (path.basename(Directory.current.path) != 'tools_metadata') {
fail('Please run this tool from the root of the repo.');
}
final String flutterPackagePath =
path.absolute(path.join(flutterSdkPath, 'packages/flutter/lib'));
print('Setting up an analysis context...');
final List<String> includedPaths = <String>[flutterPackagePath];
final AnalysisContextCollection collection =
AnalysisContextCollection(includedPaths: includedPaths);
if (collection.contexts.length != 1) {
fail('Expected one analysis context, found ${collection.contexts.length}.');
}
final AnalysisContext context = collection.contexts.first;
final AnalysisSession session = context.currentSession;
final List<String> files = context.contextRoot.analyzedFiles().toList();
print('Scanning Dart files...');
final List<String> libraryFiles = <String>[];
for (final String file in files) {
final SourceKind kind = await session.getSourceKind(file);
if (kind == SourceKind.LIBRARY) {
libraryFiles.add(file);
}
}
print(' ${libraryFiles.length} dart files');
print("Resolving class 'Widget'...");
final LibraryElement widgetsLibrary = await session
.getLibraryByUri('package:flutter/src/widgets/framework.dart');
final ClassElement widgetClass = widgetsLibrary.getType('Widget');
print('Resolving widget subclasses...');
final List<ClassElement> classes = <ClassElement>[];
for (final String file in libraryFiles) {
final ResolvedLibraryResult resolvedLibraryResult =
await session.getResolvedLibrary(file);
final LibraryElement lib = resolvedLibraryResult.element;
for (final Element element in lib.topLevelElements) {
if (element is! ClassElement) {
continue;
}
final ClassElement clazz = element as ClassElement;
if (clazz.allSupertypes.contains(widgetClass.thisType)) {
// Hide private classes.
final String name = clazz.name;
if (!name.startsWith('_')) {
classes.add(clazz);
}
}
}
}
print(' ${classes.length} widgets');
// Normalize the output json.
classes.sort((ClassElement a, ClassElement b) => a.name.compareTo(b.name));
final File file = File('resources/catalog/widgets.json');
print('Generating ${path.relative(path.absolute(file.path))}...');
final List<Map<String, Object>> widgets = <Map<String, Object>>[];
for (final ClassElement c in classes) {
widgets.add(_convertToJson(c, widgetClass));
}
final Map<String, String> versionInfo = calculateFlutterVersion();
final Map<String, dynamic> json = <String, dynamic>{
'flutter': <String, dynamic>{
'version': versionInfo['frameworkVersion'],
'channel': versionInfo['channel'],
},
'widgets': widgets,
};
const JsonEncoder encoder = JsonEncoder.withIndent(' ');
final String output = encoder.convert(json);
file.writeAsStringSync('$output\n');
final int kb = (file.lengthSync() + 1023) ~/ 1024;
print(' ${kb}kb');
}