mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
const finder (flutter/engine#15668)
This commit is contained in:
parent
0eb30b4fcd
commit
1a91d5fb85
@ -37,6 +37,7 @@ group("flutter") {
|
||||
|
||||
if (current_toolchain == host_toolchain) {
|
||||
public_deps += [ "$flutter_root/shell/testing" ]
|
||||
public_deps += [ "//flutter/tools/const_finder" ]
|
||||
}
|
||||
|
||||
if (is_fuchsia && using_fuchsia_sdk) {
|
||||
|
||||
@ -307,8 +307,16 @@ def RunDartTests(build_dir, filter, verbose_dart_snapshot):
|
||||
RunDartTest(build_dir, dart_test_file, verbose_dart_snapshot, True)
|
||||
RunDartTest(build_dir, dart_test_file, verbose_dart_snapshot, False)
|
||||
|
||||
def RunConstFinderTests(build_dir):
|
||||
test_dir = os.path.join(buildroot_dir, 'flutter', 'tools', 'const_finder', 'test')
|
||||
opts = [
|
||||
os.path.join(test_dir, 'const_finder_test.dart'),
|
||||
os.path.join(build_dir, 'gen', 'frontend_server.dart.snapshot'),
|
||||
os.path.join(build_dir, 'flutter_patched_sdk')]
|
||||
RunEngineExecutable(build_dir, os.path.join('dart-sdk', 'bin', 'dart'), None, flags=opts, cwd=test_dir)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser();
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument('--variant', dest='variant', action='store',
|
||||
default='host_debug_unopt', help='The engine build variant to run the tests for.');
|
||||
@ -344,6 +352,7 @@ def main():
|
||||
assert not IsWindows(), "Dart tests can't be run on windows. https://github.com/flutter/flutter/issues/36301."
|
||||
dart_filter = args.dart_filter.split(',') if args.dart_filter else None
|
||||
RunDartTests(build_dir, dart_filter, args.verbose_dart_snapshot)
|
||||
RunConstFinderTests(build_dir)
|
||||
|
||||
if 'java' in types:
|
||||
assert not IsWindows(), "Android engine files can't be compiled on Windows."
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
{
|
||||
"configVersion": 2,
|
||||
"packages": [
|
||||
{
|
||||
"name": "args",
|
||||
"rootUri": "../../../../third_party/dart/third_party/pkg/args",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.0"
|
||||
},
|
||||
{
|
||||
"name": "kernel",
|
||||
"rootUri": "../../../../third_party/dart/pkg/kernel",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.2"
|
||||
},
|
||||
{
|
||||
"name": "meta",
|
||||
"rootUri": "../../../../third_party/dart/pkg/meta",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "1.12"
|
||||
},
|
||||
{
|
||||
"name": "path",
|
||||
"rootUri": "../../../../third_party/dart/third_party/pkg/path",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.0"
|
||||
},
|
||||
{
|
||||
"name": "const_finder",
|
||||
"rootUri": "../",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.4"
|
||||
}
|
||||
],
|
||||
"generated": "2020-01-16T19:11:54.963296Z",
|
||||
"generator": "pub",
|
||||
"generatorVersion": "2.7.0"
|
||||
}
|
||||
6
engine/src/flutter/tools/const_finder/.gitignore
vendored
Normal file
6
engine/src/flutter/tools/const_finder/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*.dill
|
||||
|
||||
!.dart_tool
|
||||
!.dart_tool/package_config.json
|
||||
!.packages
|
||||
!test/fixtures/.packages
|
||||
6
engine/src/flutter/tools/const_finder/.packages
Normal file
6
engine/src/flutter/tools/const_finder/.packages
Normal file
@ -0,0 +1,6 @@
|
||||
# Generated by pub on 2020-01-16 11:11:54.947929.
|
||||
args:../../../third_party/dart/third_party/pkg/args/lib/
|
||||
kernel:../../../third_party/dart/pkg/kernel/lib/
|
||||
meta:../../../third_party/dart/pkg/meta/lib/
|
||||
path:../../../third_party/dart/third_party/pkg/path/lib/
|
||||
const_finder:lib/
|
||||
23
engine/src/flutter/tools/const_finder/BUILD.gn
Normal file
23
engine/src/flutter/tools/const_finder/BUILD.gn
Normal file
@ -0,0 +1,23 @@
|
||||
# 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("//third_party/dart/utils/application_snapshot.gni")
|
||||
|
||||
application_snapshot("const_finder") {
|
||||
main_dart = "bin/main.dart"
|
||||
dot_packages = ".packages"
|
||||
|
||||
training_args = [ "--help" ]
|
||||
|
||||
inputs = [
|
||||
"bin/main.dart",
|
||||
"lib/const_finder.dart",
|
||||
".packages",
|
||||
".dart_tool/package_config.json",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//flutter/flutter_frontend_server:frontend_server",
|
||||
]
|
||||
}
|
||||
11
engine/src/flutter/tools/const_finder/README.md
Normal file
11
engine/src/flutter/tools/const_finder/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Const Finder
|
||||
|
||||
This program uses package:kernel from the Dart SDK in //third_party.
|
||||
|
||||
A snapshot is created via the build rules in BUILD.gn. This is then vended
|
||||
to the Flutter tool, which uses it to find `const` creations of `IconData`
|
||||
classes. The information from this can then be passed to the `font-subset` tool
|
||||
to create a smaller icon font file specific to the application.
|
||||
|
||||
Once [flutter/flutter#47162](https://github.com/flutter/flutter/issues/47162) is
|
||||
resolved, this package should be moved to the flutter tool.
|
||||
86
engine/src/flutter/tools/const_finder/bin/main.dart
Normal file
86
engine/src/flutter/tools/const_finder/bin/main.dart
Normal file
@ -0,0 +1,86 @@
|
||||
// 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.')
|
||||
..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')
|
||||
..addOption('class-name',
|
||||
help: 'The class name for the class to find.', valueHelp: 'IconData')
|
||||
..addSeparator('Optional arguments:')
|
||||
..addFlag('pretty',
|
||||
defaultsTo: false,
|
||||
negatable: false,
|
||||
help: 'Pretty print JSON output (defaults to false).')
|
||||
..addFlag('help',
|
||||
abbr: 'h',
|
||||
defaultsTo: false,
|
||||
negatable: false,
|
||||
help: 'Print usage and exit');
|
||||
|
||||
final ArgResults argResults = parser.parse(args);
|
||||
T getArg<T>(String name) => argResults[name] as T;
|
||||
|
||||
if (getArg<bool>('help')) {
|
||||
stdout.writeln(parser.usage);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
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'),
|
||||
);
|
||||
|
||||
final JsonEncoder encoder = getArg<bool>('pretty')
|
||||
? const JsonEncoder.withIndent(' ')
|
||||
: const JsonEncoder();
|
||||
|
||||
stdout.writeln(encoder.convert(finder.findInstances()));
|
||||
}
|
||||
123
engine/src/flutter/tools/const_finder/lib/const_finder.dart
Normal file
123
engine/src/flutter/tools/const_finder/lib/const_finder.dart
Normal file
@ -0,0 +1,123 @@
|
||||
// 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 'package:kernel/kernel.dart' hide MapEntry;
|
||||
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),
|
||||
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 List<Map<String, dynamic>> constantInstances;
|
||||
final List<Map<String, dynamic>> nonConstantLocations;
|
||||
|
||||
bool _matches(Class node) {
|
||||
return node.enclosingLibrary.canonicalName.name == classLibraryUri &&
|
||||
node.name == className;
|
||||
}
|
||||
|
||||
@override
|
||||
void visitConstructorInvocation(ConstructorInvocation node) {
|
||||
final Class parentClass = node.target.parent as Class;
|
||||
if (!_matches(parentClass)) {
|
||||
super.visitConstructorInvocation(node);
|
||||
}
|
||||
nonConstantLocations.add(<String, dynamic>{
|
||||
'file': node.location.file.toString(),
|
||||
'line': node.location.line,
|
||||
'column': node.location.column,
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void visitInstanceConstantReference(InstanceConstant node) {
|
||||
if (!_matches(node.classNode)) {
|
||||
return;
|
||||
}
|
||||
final Map<String, dynamic> instance = <String, dynamic>{};
|
||||
for (MapEntry<Reference, Constant> kvp in node.fieldValues.entries) {
|
||||
final PrimitiveConstant<dynamic> value = kvp.value as PrimitiveConstant<dynamic>;
|
||||
instance[kvp.key.canonicalName.name] = value.value;
|
||||
}
|
||||
constantInstances.add(instance);
|
||||
}
|
||||
}
|
||||
|
||||
/// A kernel AST visitor that finds const references.
|
||||
class ConstFinder {
|
||||
/// Creates a new ConstFinder class. All arguments are required and must not
|
||||
/// 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);
|
||||
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".';
|
||||
}
|
||||
35
engine/src/flutter/tools/const_finder/pubspec.yaml
Normal file
35
engine/src/flutter/tools/const_finder/pubspec.yaml
Normal file
@ -0,0 +1,35 @@
|
||||
# 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.
|
||||
|
||||
name: const_finder
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: ">=2.4.0 <3.0.0"
|
||||
|
||||
# Do not add any dependencies that require more than what is provided in
|
||||
# //third_party/dart/pkg or //third_party/dart/third_party/pkg.
|
||||
# In particular, package:test is not usable here.
|
||||
|
||||
# If you do add packages here, make sure you can run `pub get --offline`, and
|
||||
# check the .packages and .package_config to make sure all the paths are
|
||||
# relative to this directory into //third_party/dart
|
||||
|
||||
dependencies:
|
||||
args: any
|
||||
meta: any
|
||||
kernel: any
|
||||
|
||||
dev_dependencies:
|
||||
path: any
|
||||
|
||||
dependency_overrides:
|
||||
args:
|
||||
path: ../../../third_party/dart/third_party/pkg/args
|
||||
kernel:
|
||||
path: ../../../third_party/dart/pkg/kernel
|
||||
meta:
|
||||
path: ../../../third_party/dart/pkg/meta
|
||||
path:
|
||||
path: ../../../third_party/dart/third_party/pkg/path
|
||||
@ -0,0 +1,136 @@
|
||||
// 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' show jsonEncode;
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:const_finder/const_finder.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
void expect<T>(T value, T expected) {
|
||||
if (value != expected) {
|
||||
stderr.writeln('Expected: $expected');
|
||||
stderr.writeln('Actual: $value');
|
||||
exitCode = -1;
|
||||
}
|
||||
}
|
||||
|
||||
final String basePath =
|
||||
path.canonicalize(path.join(path.dirname(Platform.script.path), '..'));
|
||||
final String fixtures = path.join(basePath, 'test', 'fixtures');
|
||||
final String consts = path.join(fixtures, 'lib', 'consts.dart');
|
||||
final String dotPackages = path.join(fixtures, '.packages');
|
||||
final String constsAndNon = path.join(fixtures, 'lib', 'consts_and_non.dart');
|
||||
final String constsDill = path.join(fixtures, 'consts.dill');
|
||||
final String constsAndNonDill = path.join(fixtures, 'consts_and_non.dill');
|
||||
|
||||
// This test is assuming the `dart` used to invoke the tests is compatible
|
||||
// with the version of package:kernel in //third-party/dart/pkg/kernel
|
||||
final String dart = Platform.resolvedExecutable;
|
||||
final String bat = Platform.isWindows ? '.bat' : '';
|
||||
|
||||
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',
|
||||
);
|
||||
|
||||
expect<String>(
|
||||
jsonEncode(finder.findInstances()),
|
||||
jsonEncode(<String, dynamic>{
|
||||
'constantInstances': <Map<String, dynamic>>[
|
||||
<String, dynamic>{'stringValue': '1', 'intValue': 1},
|
||||
<String, dynamic>{'stringValue': '2', 'intValue': 2}
|
||||
],
|
||||
'nonConstantLocations': <dynamic>[],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
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',
|
||||
);
|
||||
|
||||
expect<String>(
|
||||
jsonEncode(finder.findInstances()),
|
||||
jsonEncode(<String, dynamic>{
|
||||
'constantInstances': <dynamic>[
|
||||
<String, dynamic>{'stringValue': '1', 'intValue': 1}
|
||||
],
|
||||
'nonConstantLocations': <dynamic>[
|
||||
<String, dynamic>{
|
||||
'file': 'file://$fixtures/lib/consts_and_non.dart',
|
||||
'line': 12,
|
||||
'column': 26
|
||||
},
|
||||
<String, dynamic>{
|
||||
'file': 'file://$fixtures/lib/consts_and_non.dart',
|
||||
'line': 14,
|
||||
'column': 26
|
||||
},
|
||||
]
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> main(List<String> args) async {
|
||||
if (args.length != 2) {
|
||||
stderr.writeln('The first argument must be the path to the forntend server dill.');
|
||||
stderr.writeln('The second argument must be the path to the flutter_patched_sdk');
|
||||
exit(-1);
|
||||
}
|
||||
final String frontendServer = args[0];
|
||||
final String sdkRoot = args[1];
|
||||
try {
|
||||
void _checkProcessResult(ProcessResult result) {
|
||||
if (result.exitCode != 0) {
|
||||
stdout.writeln(result.stdout);
|
||||
stderr.writeln(result.stderr);
|
||||
}
|
||||
expect(result.exitCode, 0);
|
||||
}
|
||||
|
||||
stdout.writeln('Generating kernel fixtures...');
|
||||
stdout.writeln(consts);
|
||||
_checkProcessResult(Process.runSync(dart, <String>[
|
||||
frontendServer,
|
||||
'--sdk-root=$sdkRoot',
|
||||
'--target=flutter',
|
||||
'--aot',
|
||||
'--tfa',
|
||||
'--packages=$dotPackages',
|
||||
'--output-dill=$constsDill',
|
||||
consts,
|
||||
]));
|
||||
|
||||
_checkProcessResult(Process.runSync(dart, <String>[
|
||||
frontendServer,
|
||||
'--sdk-root=$sdkRoot',
|
||||
'--target=flutter',
|
||||
'--aot',
|
||||
'--tfa',
|
||||
'--packages=$dotPackages',
|
||||
'--output-dill=$constsAndNonDill',
|
||||
constsAndNon,
|
||||
]));
|
||||
|
||||
_checkConsts();
|
||||
_checkNonConsts();
|
||||
} finally {
|
||||
try {
|
||||
File(constsDill).deleteSync();
|
||||
File(constsAndNonDill).deleteSync();
|
||||
} finally {
|
||||
stdout.writeln('Tests ${exitCode == 0 ? 'succeeded' : 'failed'} - exit code: $exitCode');
|
||||
}
|
||||
}
|
||||
}
|
||||
2
engine/src/flutter/tools/const_finder/test/fixtures/.packages
vendored
Normal file
2
engine/src/flutter/tools/const_finder/test/fixtures/.packages
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# Generated by pub on 2020-01-15 10:08:29.776333.
|
||||
const_finder_fixtures:lib/
|
||||
17
engine/src/flutter/tools/const_finder/test/fixtures/lib/consts.dart
vendored
Normal file
17
engine/src/flutter/tools/const_finder/test/fixtures/lib/consts.dart
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
// 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:core';
|
||||
|
||||
import 'target.dart';
|
||||
|
||||
void main() {
|
||||
const Target target1 = Target('1', 1);
|
||||
const Target target2 = Target('2', 2);
|
||||
// ignore: unused_local_variable
|
||||
const Target target3 = Target('3', 3); // should be tree shaken out.
|
||||
target1.hit();
|
||||
target2.hit();
|
||||
}
|
||||
|
||||
17
engine/src/flutter/tools/const_finder/test/fixtures/lib/consts_and_non.dart
vendored
Normal file
17
engine/src/flutter/tools/const_finder/test/fixtures/lib/consts_and_non.dart
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
// 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.
|
||||
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
import 'dart:core';
|
||||
|
||||
import 'target.dart';
|
||||
|
||||
void main() {
|
||||
const Target target1 = Target('1', 1);
|
||||
final Target target2 = Target('2', 2);
|
||||
// ignore: unused_local_variable
|
||||
final Target target3 = Target('3', 3); // should be tree shaken out.
|
||||
target1.hit();
|
||||
target2.hit();
|
||||
}
|
||||
14
engine/src/flutter/tools/const_finder/test/fixtures/lib/target.dart
vendored
Normal file
14
engine/src/flutter/tools/const_finder/test/fixtures/lib/target.dart
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// 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.
|
||||
|
||||
class Target {
|
||||
const Target(this.stringValue, this.intValue);
|
||||
|
||||
final String stringValue;
|
||||
final int intValue;
|
||||
|
||||
void hit() {
|
||||
print('$stringValue $intValue');
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user