Chromium Code Reviews| Index: pkg/kernel/lib/canonical_name.dart |
| diff --git a/pkg/kernel/lib/canonical_name.dart b/pkg/kernel/lib/canonical_name.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0638b96cf40c770ea7ef7bb3a85e4418743f0114 |
| --- /dev/null |
| +++ b/pkg/kernel/lib/canonical_name.dart |
| @@ -0,0 +1,175 @@ |
| +// 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.canonical_name; |
| + |
| +import 'ast.dart'; |
| + |
| +/// A string sequence that identifies a library, class, or member. |
| +/// |
| +/// Canonical names are organized in a prefix tree. Each node knows its |
| +/// parent, children, and the AST node it is currently bound to. |
| +/// |
| +/// The following schema specifies how the canonical name of a given object |
| +/// is defined: |
| +/// |
| +/// Library: |
| +/// URI of library |
| +/// |
| +/// Class: |
| +/// URI of enclosing library |
|
kustermann
2017/02/01 13:00:54
Isn't this the canonical name of the enclosing lib
asgerf
2017/02/02 12:30:27
They are the same thing. I thought it would be cle
kustermann
2017/02/03 11:48:20
Up to you, but for all the other things, like Fiel
asgerf
2017/02/03 12:47:38
Done.
|
| +/// Name of class |
| +/// |
| +/// Constructor: |
| +/// Canonical name of enclosing class or library |
| +/// "@constructors" |
| +/// Qualified name |
| +/// |
| +/// Field: |
| +/// Canonical name of enclosing class or library |
| +/// "@fields" |
| +/// Qualified name |
| +/// |
| +/// Procedure that is not an accessor: |
| +/// Canonical name of enclosing class or library |
| +/// "@methods" |
| +/// Qualified name |
| +/// |
| +/// Procedure that is a getter: |
| +/// Canonical name of enclosing class or library |
| +/// "@getters" |
| +/// Qualified name |
| +/// |
| +/// Procedure that is a setter: |
| +/// Canonical name of enclosing class or library |
| +/// "@setters" |
| +/// Qualified name |
| +/// |
| +/// Qualified name: |
| +/// if private: URI of library |
| +/// Name text |
| +/// |
| +/// The "qualified name" allows a member to have a name that is private to |
| +/// a library other than the one containing that member. |
| +class CanonicalName { |
| + final CanonicalName parent; |
| + final String name; |
| + |
| + Map<String, CanonicalName> _children; |
| + |
| + /// The library, class, or member bound to this name. |
| + LinkedNode definition; |
| + |
| + /// Temporary index used during serialization. |
| + int index = -1; |
| + |
| + CanonicalName._(this.parent, this.name) { |
| + assert(name != null); |
| + } |
| + |
| + CanonicalName.root() |
| + : parent = null, |
| + name = ''; |
| + |
| + /// Used as temporary measure to get the dart2js-kernel adaptor working. |
| + /// |
| + /// This canonical name cannot be used in serialization but can hold in-memory |
| + /// references. |
| + CanonicalName.dummy() |
| + : parent = null, |
| + name = 'dummy'; |
| + |
| + bool get isRoot => parent == null; |
| + |
| + Iterable<CanonicalName> get children => |
| + _children?.values ?? const <CanonicalName>[]; |
| + |
| + CanonicalName getChild(String name) { |
| + var map = _children ??= <String, CanonicalName>{}; |
| + return map[name] ??= new CanonicalName._(this, name); |
| + } |
| + |
| + CanonicalName getChildFromUri(Uri uri) { |
| + // Note that the Uri class caches its string representation, and all library |
| + // URIs will be stringified for serialization anyway, so there is no |
| + // significant cost for converting the Uri to a string here. |
| + return getChild('$uri'); |
| + } |
| + |
| + CanonicalName getChildFromQualifiedName(Name name) { |
| + return name.isPrivate |
| + ? getChild(name.libraryName.name).getChild(name.name) |
| + : getChild(name.name); |
| + } |
| + |
| + CanonicalName getChildFromMember(Member member) { |
| + return getChild(getMemberQualifier(member)) |
| + .getChildFromQualifiedName(member.name); |
| + } |
| + |
| + void linkTo(LinkedNode target) { |
|
ahe
2017/01/30 17:16:16
Call this bind?
asgerf
2017/02/02 12:30:27
Changed to bindTo
|
| + if (definition == target) return; |
| + if (definition != null) { |
| + throw '$this is already bound'; |
| + } |
| + if (target.canonicalName != null) { |
| + throw 'Cannot bind $this to $target, target is already bound'; |
| + } |
| + target.canonicalName = this; |
| + this.definition = target; |
| + } |
| + |
| + void unlink() { |
| + if (definition == null) return; |
| + assert(definition.canonicalName == this); |
| + definition.canonicalName = null; |
| + definition = null; |
|
kustermann
2017/02/01 13:00:54
Should this unlink() not also update the _children
asgerf
2017/02/02 12:30:27
'unlink' is not meant to "destroy" the name. It sh
|
| + } |
| + |
| + String toString() => parent == null ? 'root' : '$parent::$name'; |
| + |
| + Library get asLibrary { |
| + if (definition == null) throw '$this is not bound'; |
| + return definition as Library; |
| + } |
| + |
| + Class get asClass { |
| + if (definition == null) throw '$this is not bound'; |
| + return definition as Class; |
| + } |
| + |
| + Member get asMember { |
| + if (definition == null) throw '$this is not bound'; |
| + return definition as Member; |
| + } |
| + |
| + Constructor get asConstructor { |
| + if (definition == null) throw '$this is not bound'; |
| + return definition as Constructor; |
| + } |
| + |
| + Procedure get asProcedure { |
| + if (definition == null) throw '$this is not bound'; |
| + return definition as Procedure; |
| + } |
| + |
| + Field get asField { |
| + if (definition == null) throw '$this is not bound'; |
| + return definition as Field; |
| + } |
| + |
| + static String getMemberQualifier(Member member) { |
| + if (member is Procedure) { |
| + if (member.isGetter) return '@getters'; |
| + if (member.isSetter) return '@setters'; |
| + return '@methods'; |
| + } |
| + if (member is Field) { |
| + return '@fields'; |
| + } |
| + if (member is Constructor) { |
| + return '@constructors'; |
| + } |
| + throw 'Unexpected member: $member'; |
| + } |
| +} |