| // Copyright (c) 2024, 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 '../../ast.dart'; | |
| // ------------------------------------------------------------------------ | |
| // NAMES | |
| // ------------------------------------------------------------------------ | |
| /// A public name, or a private name qualified by a library. | |
| /// | |
| /// Names are only used for expressions with dynamic dispatch, as all | |
| /// statically resolved references are represented in nameless form. | |
| /// | |
| /// [Name]s are immutable and compare based on structural equality, and they | |
| /// are not AST nodes. | |
| /// | |
| /// The [toString] method returns a human-readable string that includes the | |
| /// library name for private names; uniqueness is not guaranteed. | |
| abstract class Name extends Node { | |
| @override | |
| final int hashCode; | |
| final String text; | |
| Reference? get libraryReference; | |
| Library? get library; | |
| bool get isPrivate; | |
| new _internal(this.hashCode, this.text); | |
| factory(String text, [Library? library]) => | |
| new Name.byReference(text, library?.reference); | |
| factory byReference(String text, Reference? libraryName) { | |
| /// Use separate subclasses for the public and private case to save memory | |
| /// for public names. | |
| if (text.startsWith('_')) { | |
| assert(libraryName != null); | |
| return new _PrivateName(text, libraryName!); | |
| } else { | |
| return new _PublicName(text); | |
| } | |
| } | |
| @override | |
| bool operator ==(other) { | |
| return other is Name && text == other.text && library == other.library; | |
| } | |
| @override | |
| R accept<R>(Visitor<R> v) => v.visitName(this); | |
| @override | |
| R accept1<R, A>(Visitor1<R, A> v, A arg) => v.visitName(this, arg); | |
| @override | |
| void visitChildren(Visitor v) { | |
| // DESIGN TODO: Should we visit the library as a library reference? | |
| } | |
| /// Returns the textual representation of this node for use in debugging. | |
| /// | |
| /// Note that this adds some nodes to a static map to ensure consistent | |
| /// naming, but that it thus also leaks memory. | |
| @override | |
| String leakingDebugToString() => astToText.debugNodeToString(this); | |
| @override | |
| void toTextInternal(AstPrinter printer) { | |
| printer.writeName(this); | |
| } | |
| /// The name of the `call` method on a function. | |
| static final Name callName = new _PublicName('call'); | |
| /// The name of the `==` operator. | |
| static final Name equalsName = new _PublicName('=='); | |
| } | |
| class _PrivateName extends Name { | |
| @override | |
| final Reference libraryReference; | |
| @override | |
| bool get isPrivate => true; | |
| new(String text, Reference libraryReference) | |
| : this.libraryReference = libraryReference, | |
| super._internal(_computeHashCode(text, libraryReference), text); | |
| @override | |
| String toString() => toStringInternal(); | |
| @override | |
| String toStringInternal() => '$library::$text'; | |
| @override | |
| Library get library => libraryReference.asLibrary; | |
| static int _computeHashCode(String name, Reference libraryReference) { | |
| // TODO(cstefantsova): Factor in [libraryReference] in a non-deterministic | |
| // way into the result. Note, the previous code here was the following: | |
| // return 131 * name.hashCode + 17 * | |
| // libraryReference.asLibrary._libraryId; | |
| return name.hashCode; | |
| } | |
| } | |
| class _PublicName extends Name { | |
| @override | |
| Reference? get libraryReference => null; | |
| @override | |
| Library? get library => null; | |
| @override | |
| bool get isPrivate => false; | |
| new(String text) : super._internal(text.hashCode, text); | |
| @override | |
| String toString() => toStringInternal(); | |
| } |