Files
sdk/pkg/kernel/lib/transformations/reify/analysis/program_analysis.dart
T
Karl Klose ed390e7bad Change imports in reify transformation to not use 'package:'
R=dmitryas@google.com

Change-Id: If2e1f735de9f3879fcf321af5d5fa00e291e28a8
Reviewed-on: https://dart-review.googlesource.com/16460
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
Commit-Queue: Karl Klose <karlklose@google.com>
2017-10-25 11:25:00 +00:00

107 lines
3.0 KiB
Dart

// 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 '../../../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;
}