blob: d20423687ed4dc0ba684ed8b440d5cf10593a3ec [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:convert';
import 'dart:io';
import 'package:args/args.dart';
import 'package:const_finder/const_finder.dart';
void main(List<String> args) {
final ArgParser parser = ArgParser();
parser
..addSeparator('Finds constant instances of a specified class from the\n'
'specified package, and outputs JSON like the following:')
..addSeparator('''
{
"constantInstances": [
{
"codePoint": 59470,
"fontFamily": "MaterialIcons",
"fontPackage": null,
"matchTextDirection": false
}
],
"nonConstantInstances": [
{
"file": "file:///Path/to/hello_world/lib/file.dart",
"line": 19,
"column": 11
}
]
}''')
..addSeparator('Where the "constantInstances" is a list of objects containing\n'
'the properties passed to the const constructor of the class, and\n'
'"nonConstantInstances" is a list of source locations of non-constant\n'
'creation of the specified class. Non-constant creation cannot be\n'
'statically evaluated by this tool, and callers may wish to treat them\n'
'as errors. The non-constant creation may include entries that are not\n'
'reachable at runtime.')
..addSeparator('Required arguments:')
..addOption('kernel-file',
valueHelp: 'path/to/main.dill',
help: 'The path to a kernel file to parse, which was created from the '
'main-package-uri library.',
mandatory: true)
..addOption('class-library-uri',
mandatory: true,
help: 'The package: URI of the class to find.',
valueHelp: 'package:flutter/src/widgets/icon_data.dart')
..addOption('class-name',
help: 'The class name for the class to find.',
valueHelp: 'IconData',
mandatory: true)
..addSeparator('Optional arguments:')
..addFlag('pretty',
negatable: false,
help: 'Pretty print JSON output (defaults to false).')
..addFlag('help',
abbr: 'h',
negatable: false,
help: 'Print usage and exit')
..addOption('annotation-class-name',
help: 'The class name of the annotation for classes that should be '
'ignored.',
valueHelp: 'StaticIconProvider')
..addOption('annotation-class-library-uri',
help: 'The package: URI of the class of the annotation for classes '
'that should be ignored.',
valueHelp: 'package:flutter/src/material/icons.dart');
final ArgResults argResults = parser.parse(args);
T getArg<T>(String name) => argResults[name] as T;
final String? annotationClassName = getArg<String?>('annotation-class-name');
final String? annotationClassLibraryUri = getArg<String?>('annotation-class-library-uri');
final bool annotationClassNameProvided = annotationClassName != null;
final bool annotationClassLibraryUriProvided = annotationClassLibraryUri != null;
if (annotationClassNameProvided != annotationClassLibraryUriProvided) {
throw StateError(
'If either "--annotation-class-name" or "--annotation-class-library-uri" are provided they both must be',
);
}
if (getArg<bool>('help')) {
stdout.writeln(parser.usage);
exit(0);
}
final ConstFinder finder = ConstFinder(
kernelFilePath: getArg<String>('kernel-file'),
classLibraryUri: getArg<String>('class-library-uri'),
className: getArg<String>('class-name'),
annotationClassName: annotationClassName,
annotationClassLibraryUri: annotationClassLibraryUri,
);
final JsonEncoder encoder = getArg<bool>('pretty')
? const JsonEncoder.withIndent(' ')
: const JsonEncoder();
stdout.writeln(encoder.convert(finder.findInstances()));
}