blob: e7a28d1b1c9a9e9cb6b0a6f169fed915cbea5db3 [file] [log] [blame]
// Copyright (c) 2019, 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 vm.bytecode.ast_remover;
import 'package:kernel/ast.dart' hide MapEntry;
import '../metadata/bytecode.dart';
/// Drops kernel AST for members with bytecode.
/// Can preserve removed AST and restore it if needed.
class ASTRemover extends Transformer {
final BytecodeMetadataRepository metadata;
final stashes = <Node, _Stash>{};
ASTRemover(Component component)
: metadata = component.metadata[new BytecodeMetadataRepository().tag] {
stashes[component] = new _ComponentStash(component.mainMethod,
new Map<String, MetadataRepository<dynamic>>.from(component.metadata));
component.mainMethod = null;
component.metadata.removeWhere((tag, md) => tag != metadata.tag);
}
@override
visitLibrary(Library node) {
stashes[node] = new _LibraryStash(
new List<Expression>.from(node.annotations),
new List<Field>.from(node.fields),
new List<Procedure>.from(node.procedures),
new List<Reference>.from(node.additionalExports));
node.annotations.clear();
node.fields.clear();
node.procedures.clear();
node.additionalExports.clear();
super.visitLibrary(node);
return node;
}
@override
visitLibraryDependency(LibraryDependency node) {
stashes[node] = new _LibraryDependencyStash(
new List<Expression>.from(node.annotations));
node.annotations.clear();
super.visitLibraryDependency(node);
return node;
}
// Still referenced from function types which may appear in class supertypes.
@override
visitTypedef(Typedef node) {
stashes[node] = new _TypedefStash(node.annotations);
node.annotations = const <Expression>[];
super.visitTypedef(node);
// TODO(alexmarkov): fix Typedef visitor to visit these fields.
transformList(node.positionalParameters, this, node);
transformList(node.namedParameters, this, node);
return node;
}
// May appear in typedefs.
@override
visitVariableDeclaration(VariableDeclaration node) {
stashes[node] = new _VariableDeclarationStash(node.annotations);
node.annotations = const <Expression>[];
super.visitVariableDeclaration(node);
return node;
}
@override
visitClass(Class node) {
stashes[node] = new _ClassStash(
node.annotations,
new List<Field>.from(node.fields),
new List<Procedure>.from(node.procedures),
new List<Constructor>.from(node.constructors));
node.annotations = const <Expression>[];
node.fields.clear();
node.procedures.clear();
node.constructors.clear();
super.visitClass(node);
return node;
}
void restoreAST() {
stashes.forEach((Node node, _Stash stash) {
if (node is Component) {
_ComponentStash componentStash = stash as _ComponentStash;
node.mainMethod = componentStash.mainMethod;
node.metadata.addAll(componentStash.metadata);
} else if (node is Library) {
_LibraryStash libraryStash = stash as _LibraryStash;
node.annotations.addAll(libraryStash.annotations);
node.fields.addAll(libraryStash.fields);
node.procedures.addAll(libraryStash.procedures);
node.additionalExports.addAll(libraryStash.additionalExports);
} else if (node is LibraryDependency) {
_LibraryDependencyStash libraryDependencyStash =
stash as _LibraryDependencyStash;
node.annotations.addAll(libraryDependencyStash.annotations);
} else if (node is Typedef) {
_TypedefStash typedefStash = stash as _TypedefStash;
node.annotations = typedefStash.annotations;
} else if (node is VariableDeclaration) {
_VariableDeclarationStash variableDeclarationStash =
stash as _VariableDeclarationStash;
node.annotations = variableDeclarationStash.annotations;
} else if (node is Class) {
_ClassStash classStash = stash as _ClassStash;
node.annotations = classStash.annotations;
node.fields.addAll(classStash.fields);
node.procedures.addAll(classStash.procedures);
node.constructors.addAll(classStash.constructors);
} else {
throw 'Unexpected ${node.runtimeType} $node';
}
});
}
}
abstract class _Stash {}
class _ClassStash extends _Stash {
final List<Expression> annotations;
final List<Field> fields;
final List<Procedure> procedures;
final List<Constructor> constructors;
_ClassStash(
this.annotations, this.fields, this.procedures, this.constructors);
}
class _LibraryStash extends _Stash {
final List<Expression> annotations;
final List<Field> fields;
final List<Procedure> procedures;
final List<Reference> additionalExports;
_LibraryStash(
this.annotations, this.fields, this.procedures, this.additionalExports);
}
class _LibraryDependencyStash extends _Stash {
final List<Expression> annotations;
_LibraryDependencyStash(this.annotations);
}
class _TypedefStash extends _Stash {
final List<Expression> annotations;
_TypedefStash(this.annotations);
}
class _VariableDeclarationStash extends _Stash {
final List<Expression> annotations;
_VariableDeclarationStash(this.annotations);
}
class _ComponentStash extends _Stash {
final Procedure mainMethod;
final Map<String, MetadataRepository<dynamic>> metadata;
_ComponentStash(this.mainMethod, this.metadata);
}