mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Const finder fixes (#15880)
This commit is contained in:
parent
7e53e730b7
commit
80bc8559a0
@ -43,10 +43,6 @@ void main(List<String> 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<String> args) {
|
||||
|
||||
final ConstFinder finder = ConstFinder(
|
||||
kernelFilePath: getArg<String>('kernel-file'),
|
||||
targetLibraryUri: getArg<String>('main-library-uri'),
|
||||
classLibraryUri: getArg<String>('class-library-uri'),
|
||||
className: getArg<String>('class-name'),
|
||||
);
|
||||
|
||||
@ -8,28 +8,25 @@ import 'package:meta/meta.dart';
|
||||
class _ConstVisitor extends RecursiveVisitor<void> {
|
||||
_ConstVisitor(
|
||||
this.kernelFilePath,
|
||||
this.targetLibraryUri,
|
||||
this.classLibraryUri,
|
||||
this.className,
|
||||
) : assert(kernelFilePath != null),
|
||||
assert(targetLibraryUri != null),
|
||||
assert(classLibraryUri != null),
|
||||
assert(className != null),
|
||||
_visitedInstnaces = <String>{},
|
||||
constantInstances = <Map<String, dynamic>>[],
|
||||
nonConstantLocations = <Map<String, dynamic>>[];
|
||||
|
||||
/// 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<String> _visitedInstnaces;
|
||||
final List<Map<String, dynamic>> constantInstances;
|
||||
final List<Map<String, dynamic>> nonConstantLocations;
|
||||
|
||||
@ -43,6 +40,7 @@ class _ConstVisitor extends RecursiveVisitor<void> {
|
||||
final Class parentClass = node.target.parent as Class;
|
||||
if (!_matches(parentClass)) {
|
||||
super.visitConstructorInvocation(node);
|
||||
return;
|
||||
}
|
||||
nonConstantLocations.add(<String, dynamic>{
|
||||
'file': node.location.file.toString(),
|
||||
@ -53,15 +51,22 @@ class _ConstVisitor extends RecursiveVisitor<void> {
|
||||
|
||||
@override
|
||||
void visitInstanceConstantReference(InstanceConstant node) {
|
||||
node.fieldValues.values.whereType<InstanceConstant>().forEach(visitInstanceConstantReference);
|
||||
if (!_matches(node.classNode)) {
|
||||
super.visitInstanceConstantReference(node);
|
||||
return;
|
||||
}
|
||||
final Map<String, dynamic> instance = <String, dynamic>{};
|
||||
for (MapEntry<Reference, Constant> kvp in node.fieldValues.entries) {
|
||||
if (kvp.value is! PrimitiveConstant<dynamic>) {
|
||||
continue;
|
||||
}
|
||||
final PrimitiveConstant<dynamic> value = kvp.value as PrimitiveConstant<dynamic>;
|
||||
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<String, dynamic> findInstances() {
|
||||
final Library root = _getRoot();
|
||||
root.visitChildren(_visitor);
|
||||
_visitor._visitedInstnaces.clear();
|
||||
for (Library library in loadComponentFromBinary(_visitor.kernelFilePath).libraries) {
|
||||
library.visitChildren(_visitor);
|
||||
}
|
||||
return <String, dynamic>{
|
||||
'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".';
|
||||
}
|
||||
|
||||
@ -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(<String, dynamic>{
|
||||
'constantInstances': <Map<String, dynamic>>[
|
||||
<String, dynamic>{'stringValue': '1', 'intValue': 1},
|
||||
<String, dynamic>{'stringValue': '2', 'intValue': 2}
|
||||
<String, dynamic>{'stringValue': '1', 'intValue': 1, 'targetValue': null},
|
||||
<String, dynamic>{'stringValue': '4', 'intValue': 4, 'targetValue': null},
|
||||
<String, dynamic>{'stringValue': '2', 'intValue': 2},
|
||||
<String, dynamic>{'stringValue': '6', 'intValue': 6, 'targetValue': null},
|
||||
<String, dynamic>{'stringValue': '8', 'intValue': 8, 'targetValue': null},
|
||||
<String, dynamic>{'stringValue': '10', 'intValue': 10, 'targetValue': null},
|
||||
<String, dynamic>{'stringValue': '9', 'intValue': 9},
|
||||
<String, dynamic>{'stringValue': '7', 'intValue': 7, 'targetValue': null},
|
||||
<String, dynamic>{'stringValue': 'package', 'intValue':-1, 'targetValue': null},
|
||||
],
|
||||
'nonConstantLocations': <dynamic>[],
|
||||
}),
|
||||
@ -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(<String, dynamic>{
|
||||
'constantInstances': <dynamic>[
|
||||
<String, dynamic>{'stringValue': '1', 'intValue': 1}
|
||||
<String, dynamic>{'stringValue': '1', 'intValue': 1, 'targetValue': null},
|
||||
<String, dynamic>{'stringValue': '6', 'intValue': 6, 'targetValue': null},
|
||||
<String, dynamic>{'stringValue': '8', 'intValue': 8, 'targetValue': null},
|
||||
<String, dynamic>{'stringValue': '10', 'intValue': 10, 'targetValue': null},
|
||||
<String, dynamic>{'stringValue': '9', 'intValue': 9},
|
||||
<String, dynamic>{'stringValue': '7', 'intValue': 7, 'targetValue': null},
|
||||
],
|
||||
'nonConstantLocations': <dynamic>[
|
||||
<String, dynamic>{
|
||||
'file': 'file://$fixtures/lib/consts_and_non.dart',
|
||||
'line': 12,
|
||||
'column': 26
|
||||
'line': 14,
|
||||
'column': 26,
|
||||
},
|
||||
<String, dynamic>{
|
||||
'file': 'file://$fixtures/lib/consts_and_non.dart',
|
||||
'line': 14,
|
||||
'column': 26
|
||||
'line': 17,
|
||||
'column': 26,
|
||||
},
|
||||
<String, dynamic>{
|
||||
'file': 'file://$fixtures/lib/consts_and_non.dart',
|
||||
'line': 19,
|
||||
'column': 26,
|
||||
},
|
||||
<String, dynamic>{
|
||||
'file': 'file://$fixtures/pkg/package.dart',
|
||||
'line': 10,
|
||||
'column': 25,
|
||||
}
|
||||
]
|
||||
}),
|
||||
);
|
||||
|
||||
1
tools/const_finder/test/fixtures/.packages
vendored
1
tools/const_finder/test/fixtures/.packages
vendored
@ -1,2 +1,3 @@
|
||||
# Generated by pub on 2020-01-15 10:08:29.776333.
|
||||
const_finder_fixtures:lib/
|
||||
const_finder_fixtures_package:pkg/
|
||||
30
tools/const_finder/test/fixtures/lib/consts.dart
vendored
30
tools/const_finder/test/fixtures/lib/consts.dart
vendored
@ -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);
|
||||
}
|
||||
|
||||
@ -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); // should be tree shaken out.
|
||||
final Target target3 = Target('3', 3, Target('5', 5, null)); // should be tree shaken out.
|
||||
// ignore: unused_local_variable
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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');
|
||||
|
||||
12
tools/const_finder/test/fixtures/pkg/package.dart
vendored
Normal file
12
tools/const_finder/test/fixtures/pkg/package.dart
vendored
Normal file
@ -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();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user