未验证 提交 80bc8559 编写于 作者: D Dan Field 提交者: GitHub

Const finder fixes (#15880)

上级 7e53e730
......@@ -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,
}
]
}),
);
......
# 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
......@@ -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, 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);
}
......@@ -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');
......
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();
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册