diff --git a/tools/const_finder/bin/main.dart b/tools/const_finder/bin/main.dart index d29a95711898335a6d1e57bfa3fdedb1a1014cf0..3d0cdf4d89121031088ce34b6d0fd1beaa7c8096 100644 --- a/tools/const_finder/bin/main.dart +++ b/tools/const_finder/bin/main.dart @@ -43,10 +43,6 @@ void main(List args) { valueHelp: 'path/to/main.dill', help: 'The path to a kernel file to parse, which was created from the ' 'main-package-uri library.') - ..addOption('main-library-uri', - help: 'The package: URI to treat as the main entrypoint library ' - '(the same package used to create the kernel-file).', - valueHelp: 'package:hello_world/main.dart') ..addOption('class-library-uri', help: 'The package: URI of the class to find.', valueHelp: 'package:flutter/src/widgets/icon_data.dart') @@ -73,7 +69,6 @@ void main(List args) { final ConstFinder finder = ConstFinder( kernelFilePath: getArg('kernel-file'), - targetLibraryUri: getArg('main-library-uri'), classLibraryUri: getArg('class-library-uri'), className: getArg('class-name'), ); diff --git a/tools/const_finder/lib/const_finder.dart b/tools/const_finder/lib/const_finder.dart index b40ac249d990129793eaf16cd53ab4667f50f5ef..1eb8776a91f4032341520eb991db27243de3ecce 100644 --- a/tools/const_finder/lib/const_finder.dart +++ b/tools/const_finder/lib/const_finder.dart @@ -8,28 +8,25 @@ import 'package:meta/meta.dart'; class _ConstVisitor extends RecursiveVisitor { _ConstVisitor( this.kernelFilePath, - this.targetLibraryUri, this.classLibraryUri, this.className, ) : assert(kernelFilePath != null), - assert(targetLibraryUri != null), assert(classLibraryUri != null), assert(className != null), + _visitedInstnaces = {}, constantInstances = >[], nonConstantLocations = >[]; /// The path to the file to open. final String kernelFilePath; - /// The library URI for the main entrypoint of the target library. - final String targetLibraryUri; - /// The library URI for the class to find. final String classLibraryUri; /// The name of the class to find. final String className; + final Set _visitedInstnaces; final List> constantInstances; final List> nonConstantLocations; @@ -43,6 +40,7 @@ class _ConstVisitor extends RecursiveVisitor { final Class parentClass = node.target.parent as Class; if (!_matches(parentClass)) { super.visitConstructorInvocation(node); + return; } nonConstantLocations.add({ 'file': node.location.file.toString(), @@ -53,15 +51,22 @@ class _ConstVisitor extends RecursiveVisitor { @override void visitInstanceConstantReference(InstanceConstant node) { + node.fieldValues.values.whereType().forEach(visitInstanceConstantReference); if (!_matches(node.classNode)) { + super.visitInstanceConstantReference(node); return; } final Map instance = {}; for (MapEntry kvp in node.fieldValues.entries) { + if (kvp.value is! PrimitiveConstant) { + continue; + } final PrimitiveConstant value = kvp.value as PrimitiveConstant; instance[kvp.key.canonicalName.name] = value.value; } - constantInstances.add(instance); + if (_visitedInstnaces.add(instance.toString())) { + constantInstances.add(instance); + } } } @@ -71,53 +76,27 @@ class ConstFinder { /// be null. /// /// The `kernelFilePath` is the path to a dill (kernel) file to process. - /// - /// The `targetLibraryUri` is the `package:` URI of the main entrypoint to - /// search from. - /// - /// - /// ConstFinder({ @required String kernelFilePath, - @required String targetLibraryUri, @required String classLibraryUri, @required String className, }) : _visitor = _ConstVisitor( kernelFilePath, - targetLibraryUri, classLibraryUri, className, ); final _ConstVisitor _visitor; - Library _getRoot() { - final Component binary = loadComponentFromBinary(_visitor.kernelFilePath); - return binary.libraries.firstWhere( - (Library library) => library.canonicalName.name == _visitor.targetLibraryUri, - orElse: () => throw LibraryNotFoundException._(_visitor.targetLibraryUri), - ); - } - /// Finds all instances Map findInstances() { - final Library root = _getRoot(); - root.visitChildren(_visitor); + _visitor._visitedInstnaces.clear(); + for (Library library in loadComponentFromBinary(_visitor.kernelFilePath).libraries) { + library.visitChildren(_visitor); + } return { 'constantInstances': _visitor.constantInstances, 'nonConstantLocations': _visitor.nonConstantLocations, }; } } - -/// Exception thrown by [ConstFinder.findInstances] when the target library -/// is not found. -class LibraryNotFoundException implements Exception { - const LibraryNotFoundException._(this.targetLibraryUri); - - /// The library target URI that could not be found. - final String targetLibraryUri; - - @override - String toString() => 'Could not find target library for "$targetLibraryUri".'; -} diff --git a/tools/const_finder/test/const_finder_test.dart b/tools/const_finder/test/const_finder_test.dart index cc9a2761755f86bb95a45d9ec2f76571800977c3..dac3a465a9ee2fd8de3ef47dad5c284383ddf526 100644 --- a/tools/const_finder/test/const_finder_test.dart +++ b/tools/const_finder/test/const_finder_test.dart @@ -34,7 +34,6 @@ void _checkConsts() { print('Checking for expected constants.'); final ConstFinder finder = ConstFinder( kernelFilePath: constsDill, - targetLibraryUri: 'package:const_finder_fixtures/consts.dart', classLibraryUri: 'package:const_finder_fixtures/target.dart', className: 'Target', ); @@ -43,8 +42,15 @@ void _checkConsts() { jsonEncode(finder.findInstances()), jsonEncode({ 'constantInstances': >[ - {'stringValue': '1', 'intValue': 1}, - {'stringValue': '2', 'intValue': 2} + {'stringValue': '1', 'intValue': 1, 'targetValue': null}, + {'stringValue': '4', 'intValue': 4, 'targetValue': null}, + {'stringValue': '2', 'intValue': 2}, + {'stringValue': '6', 'intValue': 6, 'targetValue': null}, + {'stringValue': '8', 'intValue': 8, 'targetValue': null}, + {'stringValue': '10', 'intValue': 10, 'targetValue': null}, + {'stringValue': '9', 'intValue': 9}, + {'stringValue': '7', 'intValue': 7, 'targetValue': null}, + {'stringValue': 'package', 'intValue':-1, 'targetValue': null}, ], 'nonConstantLocations': [], }), @@ -55,7 +61,6 @@ void _checkNonConsts() { print('Checking for non-constant instances.'); final ConstFinder finder = ConstFinder( kernelFilePath: constsAndNonDill, - targetLibraryUri: 'package:const_finder_fixtures/consts_and_non.dart', classLibraryUri: 'package:const_finder_fixtures/target.dart', className: 'Target', ); @@ -64,19 +69,34 @@ void _checkNonConsts() { jsonEncode(finder.findInstances()), jsonEncode({ 'constantInstances': [ - {'stringValue': '1', 'intValue': 1} + {'stringValue': '1', 'intValue': 1, 'targetValue': null}, + {'stringValue': '6', 'intValue': 6, 'targetValue': null}, + {'stringValue': '8', 'intValue': 8, 'targetValue': null}, + {'stringValue': '10', 'intValue': 10, 'targetValue': null}, + {'stringValue': '9', 'intValue': 9}, + {'stringValue': '7', 'intValue': 7, 'targetValue': null}, ], 'nonConstantLocations': [ { 'file': 'file://$fixtures/lib/consts_and_non.dart', - 'line': 12, - 'column': 26 + 'line': 14, + 'column': 26, }, { 'file': 'file://$fixtures/lib/consts_and_non.dart', - 'line': 14, - 'column': 26 + 'line': 17, + 'column': 26, + }, + { + 'file': 'file://$fixtures/lib/consts_and_non.dart', + 'line': 19, + 'column': 26, }, + { + 'file': 'file://$fixtures/pkg/package.dart', + 'line': 10, + 'column': 25, + } ] }), ); diff --git a/tools/const_finder/test/fixtures/.packages b/tools/const_finder/test/fixtures/.packages index 899ade66cd7b0ca87e31984dc7ac643099bbaeba..0ef0f0b0b3019fb06f52d4a4b63f5ccdd340de05 100644 --- a/tools/const_finder/test/fixtures/.packages +++ b/tools/const_finder/test/fixtures/.packages @@ -1,2 +1,3 @@ # Generated by pub on 2020-01-15 10:08:29.776333. const_finder_fixtures:lib/ +const_finder_fixtures_package:pkg/ \ No newline at end of file diff --git a/tools/const_finder/test/fixtures/lib/consts.dart b/tools/const_finder/test/fixtures/lib/consts.dart index ef1969c491deb4a74a346914cdca80a1b125b1bd..1fd3a64bd67cbb0829e13cb366c5a5c376f71467 100644 --- a/tools/const_finder/test/fixtures/lib/consts.dart +++ b/tools/const_finder/test/fixtures/lib/consts.dart @@ -4,14 +4,38 @@ import 'dart:core'; +import 'package:const_finder_fixtures_package/package.dart'; + import 'target.dart'; void main() { - const Target target1 = Target('1', 1); - const Target target2 = Target('2', 2); + const Target target1 = Target('1', 1, null); + const Target target2 = Target('2', 2, Target('4', 4, null)); // ignore: unused_local_variable - const Target target3 = Target('3', 3); // should be tree shaken out. + const Target target3 = Target('3', 3, Target('5', 5, null)); // should be tree shaken out. target1.hit(); target2.hit(); + + blah(const Target('6', 6, null)); + + const IgnoreMe ignoreMe = IgnoreMe(Target('7', 7, null)); // IgnoreMe is ignored but 7 is not. + // ignore: prefer_const_constructors + final IgnoreMe ignoreMe2 = IgnoreMe(const Target('8', 8, null)); + // ignore: prefer_const_constructors + final IgnoreMe ignoreMe3 = IgnoreMe(const Target('9', 9, Target('10', 10, null))); + print(ignoreMe); + print(ignoreMe2); + print(ignoreMe3); + + createTargetInPackage(); } +class IgnoreMe { + const IgnoreMe([this.target]); + + final Target target; +} + +void blah(Target target) { + print(target); +} diff --git a/tools/const_finder/test/fixtures/lib/consts_and_non.dart b/tools/const_finder/test/fixtures/lib/consts_and_non.dart index d717faaeae3aeb757cd6c73839b796bf57c1f3d0..9f4eeb8d04271b03bf5644d3ab005703eb2cb472 100644 --- a/tools/const_finder/test/fixtures/lib/consts_and_non.dart +++ b/tools/const_finder/test/fixtures/lib/consts_and_non.dart @@ -5,13 +5,41 @@ // ignore_for_file: prefer_const_constructors import 'dart:core'; +import 'package:const_finder_fixtures_package/package.dart'; + import 'target.dart'; void main() { - const Target target1 = Target('1', 1); - final Target target2 = Target('2', 2); + const Target target1 = Target('1', 1, null); + final Target target2 = Target('2', 2, const Target('4', 4, null)); + + // ignore: unused_local_variable + final Target target3 = Target('3', 3, Target('5', 5, null)); // should be tree shaken out. // ignore: unused_local_variable - final Target target3 = Target('3', 3); // should be tree shaken out. + final Target target6 = Target('6', 6, null); // should be tree shaken out. target1.hit(); target2.hit(); + + blah(const Target('6', 6, null)); + + const IgnoreMe ignoreMe = IgnoreMe(Target('7', 7, null)); // IgnoreMe is ignored but 7 is not. + // ignore: prefer_const_constructors + final IgnoreMe ignoreMe2 = IgnoreMe(const Target('8', 8, null)); + // ignore: prefer_const_constructors + final IgnoreMe ignoreMe3 = IgnoreMe(const Target('9', 9, Target('10', 10, null))); + print(ignoreMe); + print(ignoreMe2); + print(ignoreMe3); + + createNonConstTargetInPackage(); +} + +class IgnoreMe { + const IgnoreMe([this.target]); + + final Target target; +} + +void blah(Target target) { + print(target); } diff --git a/tools/const_finder/test/fixtures/lib/target.dart b/tools/const_finder/test/fixtures/lib/target.dart index 779fa8691c33445a81995b8b6e81c6b176f8df62..4046216970ed9822fa4455d35f8f9fd48c861bd6 100644 --- a/tools/const_finder/test/fixtures/lib/target.dart +++ b/tools/const_finder/test/fixtures/lib/target.dart @@ -3,10 +3,11 @@ // found in the LICENSE file. class Target { - const Target(this.stringValue, this.intValue); + const Target(this.stringValue, this.intValue, this.targetValue); final String stringValue; final int intValue; + final Target targetValue; void hit() { print('$stringValue $intValue'); diff --git a/tools/const_finder/test/fixtures/pkg/package.dart b/tools/const_finder/test/fixtures/pkg/package.dart new file mode 100644 index 0000000000000000000000000000000000000000..62ba73c3575abb9062c90fe42b7483b4bdf0274f --- /dev/null +++ b/tools/const_finder/test/fixtures/pkg/package.dart @@ -0,0 +1,12 @@ +import 'package:const_finder_fixtures/target.dart'; + +void createTargetInPackage() { + const Target target = Target('package', -1, null); + target.hit(); +} + +void createNonConstTargetInPackage() { + // ignore: prefer_const_constructors + final Target target = Target('package_non', -2, null); + target.hit(); +}