| Index: pkg/kernel/lib/transformations/reify/analysis/program_analysis.dart
|
| diff --git a/pkg/kernel/lib/transformations/reify/analysis/program_analysis.dart b/pkg/kernel/lib/transformations/reify/analysis/program_analysis.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8e712d77c527ce2a5c779c9624f309c81533edc4
|
| --- /dev/null
|
| +++ b/pkg/kernel/lib/transformations/reify/analysis/program_analysis.dart
|
| @@ -0,0 +1,106 @@
|
| +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +library kernel.transformation.reify.analysis.program_analysis;
|
| +
|
| +import '../asts.dart';
|
| +import 'package:kernel/ast.dart';
|
| +
|
| +// TODO(karlklose): keep all predicates and derived information here and move
|
| +// the actual data to a builder class.
|
| +class ProgramKnowledge {
|
| + Map<Member, Set<TypeParameter>> _usedTypeVariables =
|
| + <Member, Set<TypeParameter>>{};
|
| +
|
| + Map<Member, Set<DartType>> isTests = <Member, Set<DartType>>{};
|
| +
|
| + Set<Class> _classTests;
|
| +
|
| + /// Contains all classes that are used as the declaration of a type expression
|
| + /// in a type test.
|
| + Set<Class> get classTests {
|
| + if (_classTests == null) {
|
| + _classTests = isTests.values
|
| + .expand((set) => set)
|
| + .where((DartType type) => type is InterfaceType)
|
| + .map((DartType type) => (type as InterfaceType).classNode)
|
| + .toSet();
|
| + }
|
| + return _classTests;
|
| + }
|
| +
|
| + recordTypeVariableUse(Expression expression, TypeParameter parameter) {
|
| + // TODO(karlklose): also record expression.
|
| + add(_usedTypeVariables, getEnclosingMember(expression), parameter);
|
| + }
|
| +
|
| + Set<TypeParameter> usedParameters(Member member) {
|
| + return _usedTypeVariables[member] ?? new Set<TypeParameter>();
|
| + }
|
| +
|
| + void recordIsTest(IsExpression node, DartType type) {
|
| + add(isTests, getEnclosingMember(node), type);
|
| + }
|
| +
|
| + add(Map<dynamic, Set> map, key, value) {
|
| + map.putIfAbsent(key, () => new Set()).add(value);
|
| + }
|
| +}
|
| +
|
| +typedef bool LibraryFilter(Library library);
|
| +
|
| +class ProgramAnalysis extends Visitor {
|
| + final ProgramKnowledge knowledge;
|
| + final LibraryFilter analyzeLibrary;
|
| +
|
| + ProgramAnalysis(this.knowledge, this.analyzeLibrary);
|
| +
|
| + defaultTreeNode(TreeNode node) => node.visitChildren(this);
|
| +
|
| + visitLibrary(Library library) {
|
| + if (!analyzeLibrary(library)) {
|
| + return;
|
| + }
|
| + super.visitLibrary(library);
|
| + }
|
| +
|
| + handleTypeReference(TreeNode node, DartType type) {
|
| + typeVariables(type).forEach((TypeParameter parameter) {
|
| + knowledge.recordTypeVariableUse(node, parameter);
|
| + });
|
| + }
|
| +
|
| + handleInstantiation(InvocationExpression node) {
|
| + node.arguments.types.forEach((DartType type) {
|
| + handleTypeReference(node, type);
|
| + });
|
| + }
|
| +
|
| + visitIsExpression(IsExpression node) {
|
| + knowledge.recordIsTest(node, node.type);
|
| + handleTypeReference(node, node.type);
|
| + node.visitChildren(this);
|
| + }
|
| +
|
| + visitConstructorInvocation(ConstructorInvocation node) {
|
| + handleInstantiation(node);
|
| + node.visitChildren(this);
|
| + }
|
| +
|
| + visitStaticInvocation(StaticInvocation node) {
|
| + if (node.target.kind == ProcedureKind.Factory) {
|
| + handleInstantiation(node);
|
| + }
|
| + node.visitChildren(this);
|
| + }
|
| +}
|
| +
|
| +bool _analyzeAll(Library library) => true;
|
| +
|
| +ProgramKnowledge analyze(Program program,
|
| + {LibraryFilter analyzeLibrary: _analyzeAll}) {
|
| + ProgramKnowledge knowledge = new ProgramKnowledge();
|
| + program.accept(new ProgramAnalysis(knowledge, analyzeLibrary));
|
| + return knowledge;
|
| +}
|
|
|