| // 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); |
| } |