| // Copyright (c) 2018, 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. |
| |
| part of 'serialization.dart'; |
| |
| /// Helper for looking up object library data from an [ir.Component] node. |
| class ComponentLookup { |
| final ir.Component _component; |
| |
| /// Cache of [_LibraryData] for libraries in [_component]. |
| Map<Uri, _LibraryData> _libraryMap; |
| |
| ComponentLookup(this._component); |
| |
| /// Returns the [_LibraryData] object for the library with the [canonicalUri]. |
| _LibraryData getLibraryDataByUri(Uri canonicalUri) { |
| if (_libraryMap == null) { |
| _libraryMap = {}; |
| for (ir.Library library in _component.libraries) { |
| _libraryMap[library.importUri] = new _LibraryData(library); |
| } |
| } |
| return _libraryMap[canonicalUri]; |
| } |
| } |
| |
| /// Returns a name uniquely identifying a member within its enclosing library |
| /// or class. |
| String _computeMemberName(ir.Member member) { |
| if (member.name.isPrivate && |
| member.name.libraryName != member.enclosingLibrary.reference) { |
| // TODO(33732): Handle noSuchMethod forwarders for private members from |
| // other libraries. |
| return null; |
| } |
| String name = member.name.name; |
| if (member is ir.Constructor) { |
| name = '.$name'; |
| } else if (member is ir.Procedure) { |
| if (member.kind == ir.ProcedureKind.Factory) { |
| name = '.$name'; |
| } else if (member.kind == ir.ProcedureKind.Setter) { |
| name += "="; |
| } |
| } |
| return name; |
| } |
| |
| /// Helper for looking up classes and members from an [ir.Library] node. |
| class _LibraryData { |
| /// The [ir.Library] that defines the library. |
| final ir.Library node; |
| |
| /// Cache of [_ClassData] for classes in this library. |
| Map<String, _ClassData> _classes; |
| |
| /// Cache of [ir.Typedef] nodes for typedefs in this library. |
| Map<String, ir.Typedef> _typedefs; |
| |
| /// Cache of [_MemberData] for members in this library. |
| Map<String, _MemberData> _members; |
| |
| _LibraryData(this.node); |
| |
| /// Returns the [_ClassData] for the class [name] in this library. |
| _ClassData lookupClass(String name) { |
| if (_classes == null) { |
| _classes = {}; |
| for (ir.Class cls in node.classes) { |
| assert(!_classes.containsKey(cls.name), |
| "Duplicate class '${cls.name}' in $_classes trying to add $cls."); |
| _classes[cls.name] = new _ClassData(cls); |
| } |
| } |
| return _classes[name]; |
| } |
| |
| ir.Typedef lookupTypedef(String name) { |
| if (_typedefs == null) { |
| _typedefs = {}; |
| for (ir.Typedef typedef in node.typedefs) { |
| assert( |
| !_typedefs.containsKey(typedef.name), |
| "Duplicate typedef '${typedef.name}' in $_typedefs " |
| "trying to add $typedef."); |
| _typedefs[typedef.name] = typedef; |
| } |
| } |
| return _typedefs[name]; |
| } |
| |
| /// Returns the [_MemberData] for the member uniquely identified by [name] in |
| /// this library. |
| _MemberData lookupMember(String name) { |
| if (_members == null) { |
| _members = {}; |
| for (ir.Member member in node.members) { |
| String name = _computeMemberName(member); |
| if (name == null) continue; |
| assert(!_members.containsKey(name), |
| "Duplicate member '$name' in $_members trying to add $member."); |
| _members[name] = new _MemberData(member); |
| } |
| } |
| return _members[name]; |
| } |
| |
| String toString() => '_LibraryData($node(${identityHashCode(node)}))'; |
| } |
| |
| /// Helper for looking up members from an [ir.Class] node. |
| class _ClassData { |
| /// The [ir.Class] that defines the class. |
| final ir.Class node; |
| |
| /// Cache of [_MemberData] for members in this class. |
| Map<String, _MemberData> _members; |
| |
| _ClassData(this.node); |
| |
| /// Returns the [_MemberData] for the member uniquely identified by [name] in |
| /// this class. |
| _MemberData lookupMember(String name) { |
| if (_members == null) { |
| _members = {}; |
| for (ir.Member member in node.members) { |
| String name = _computeMemberName(member); |
| if (name == null) continue; |
| assert(!_members.containsKey(name), |
| "Duplicate member '$name' in $_members trying to add $member."); |
| _members[name] = new _MemberData(member); |
| } |
| } |
| return _members[name]; |
| } |
| |
| String toString() => '_ClassData($node(${identityHashCode(node)}))'; |
| } |
| |
| /// Helper for looking up child [ir.TreeNode]s of a [ir.Member] node. |
| class _MemberData { |
| /// The [ir.Member] that defines the member. |
| final ir.Member node; |
| |
| /// Cached index to [ir.TreeNode] map used for deserialization of |
| /// [ir.TreeNode]s. |
| Map<int, ir.TreeNode> _indexToNodeMap; |
| |
| /// Cached [ir.TreeNode] to index map used for serialization of |
| /// [ir.TreeNode]s. |
| Map<ir.TreeNode, int> _nodeToIndexMap; |
| |
| _MemberData(this.node); |
| |
| void _ensureMaps() { |
| if (_indexToNodeMap == null) { |
| _indexToNodeMap = {}; |
| _nodeToIndexMap = {}; |
| node.accept( |
| new _TreeNodeIndexerVisitor(_indexToNodeMap, _nodeToIndexMap)); |
| } |
| } |
| |
| /// Returns the [ir.TreeNode] corresponding to [index] in this member. |
| ir.TreeNode getTreeNodeByIndex(int index) { |
| _ensureMaps(); |
| ir.TreeNode treeNode = _indexToNodeMap[index]; |
| assert(treeNode != null, "No TreeNode found for index $index in $node."); |
| return treeNode; |
| } |
| |
| /// Returns the index corresponding to [ir.TreeNode] in this member. |
| int getIndexByTreeNode(ir.TreeNode node) { |
| _ensureMaps(); |
| int index = _nodeToIndexMap[node]; |
| assert(index != null, "No index found for ${node.runtimeType}."); |
| return index; |
| } |
| |
| String toString() => '_MemberData($node(${identityHashCode(node)}))'; |
| } |