blob: 22b6c5c036e9f31bc9f3efbc13074b3e9678e7d7 [file] [log] [blame]
// Copyright (c) 2020, 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.
import '../ast.dart';
String nullabilityToString(Nullability nullability) {
switch (nullability) {
case Nullability.legacy:
return '*';
case Nullability.nullable:
return '?';
case Nullability.undetermined:
return '%';
case Nullability.nonNullable:
return '';
}
}
String nameToString(Name? node, {bool includeLibraryName = false}) {
if (node == null) {
return 'null';
} else if (node.library != null && includeLibraryName) {
return '${libraryNameToString(node.library)}::${node.text}';
} else {
return node.text;
}
}
String libraryNameToString(Library? node) {
return node == null ? 'null' : node.name ?? 'library ${node.importUri}';
}
String libraryReferenceToString(Reference? reference) {
if (reference == null) {
return '<missing-library-reference>';
} else {
Library? node = reference.node as Library?;
if (node != null) {
return node.importUri.toString();
} else {
CanonicalName? canonicalName = reference.canonicalName;
if (canonicalName != null) {
return qualifiedCanonicalNameToString(canonicalName,
includeLibraryName: false);
} else {
return '<unlinked-library-reference>';
}
}
}
}
String qualifiedClassNameToString(Class node,
{bool includeLibraryName = false}) {
TreeNode? parent = node.parent;
if (parent is Library && includeLibraryName) {
return libraryNameToString(parent) + '::' + classNameToString(node);
} else {
return classNameToString(node);
}
}
String qualifiedCanonicalNameToString(CanonicalName canonicalName,
{bool includeLibraryName = false,
bool includeLibraryNamesInTypes = false}) {
if (canonicalName.isRoot) {
return '<root>';
} else if (canonicalName.parent!.isRoot) {
// Library.
return 'library ${canonicalName.name}';
} else if (canonicalName.parent!.parent!.isRoot) {
// Class or extension.
if (!includeLibraryName) {
return canonicalName.name;
}
String parentName = qualifiedCanonicalNameToString(canonicalName.parent!,
includeLibraryName: includeLibraryName,
includeLibraryNamesInTypes: includeLibraryNamesInTypes);
return '$parentName::${canonicalName.name}';
} else {
// Constructor, field, procedure (factory, getter, setter etc), typedef;
// but we could technically be anywhere in the "hierarchy" --- at the
// @typedef for instance, or at the uri of a library for a private name.
CanonicalName parentNotPrivateUri = canonicalName.parent!;
if (canonicalName.name.startsWith("_")) {
parentNotPrivateUri = parentNotPrivateUri.parent!;
}
if (parentNotPrivateUri.name == CanonicalName.typedefsName) {
includeLibraryName = includeLibraryNamesInTypes;
}
if (parentNotPrivateUri.parent!.parent!.parent?.isRoot == true) {
// Parent is class (or extension).
String parentName = qualifiedCanonicalNameToString(
parentNotPrivateUri.parent!,
includeLibraryName: includeLibraryName,
includeLibraryNamesInTypes: includeLibraryNamesInTypes);
return "$parentName.${canonicalName.name}";
} else {
// Parent is library.
if (!includeLibraryName) {
return canonicalName.name;
}
String parentName = qualifiedCanonicalNameToString(
parentNotPrivateUri.parent!,
includeLibraryName: includeLibraryName,
includeLibraryNamesInTypes: includeLibraryNamesInTypes);
return '$parentName::${canonicalName.name}';
}
}
}
String qualifiedClassNameToStringByReference(Reference? reference,
{bool includeLibraryName = false}) {
if (reference == null) {
return '<missing-class-reference>';
} else {
Class? node = reference.node as Class?;
if (node != null) {
return qualifiedClassNameToString(node,
includeLibraryName: includeLibraryName);
} else {
CanonicalName? canonicalName = reference.canonicalName;
if (canonicalName != null) {
return qualifiedCanonicalNameToString(canonicalName,
includeLibraryName: includeLibraryName);
} else {
return '<unlinked-class-reference>';
}
}
}
}
String classNameToString(Class? node) {
return node == null ? 'null' : node.name;
}
String qualifiedExtensionNameToString(Extension node,
{bool includeLibraryName = false}) {
TreeNode? parent = node.parent;
if (parent is Library && includeLibraryName) {
return libraryNameToString(parent) + '::' + extensionNameToString(node);
} else {
return extensionNameToString(node);
}
}
String qualifiedExtensionNameToStringByReference(Reference? reference,
{bool includeLibraryName = false}) {
if (reference == null) {
return '<missing-extension-reference>';
} else {
Extension? node = reference.node as Extension?;
if (node != null) {
return qualifiedExtensionNameToString(node,
includeLibraryName: includeLibraryName);
} else {
CanonicalName? canonicalName = reference.canonicalName;
if (canonicalName != null) {
return qualifiedCanonicalNameToString(canonicalName,
includeLibraryName: includeLibraryName);
} else {
return '<unlinked-extension-reference>';
}
}
}
}
String extensionNameToString(Extension? node) {
return node == null ? 'null' : node.name;
}
String qualifiedExtensionTypeDeclarationNameToString(
ExtensionTypeDeclaration node,
{bool includeLibraryName = false}) {
TreeNode? parent = node.parent;
if (parent is Library && includeLibraryName) {
return libraryNameToString(parent) +
'::' +
extensionTypeDeclarationNameToString(node);
} else {
return extensionTypeDeclarationNameToString(node);
}
}
String qualifiedExtensionTypeDeclarationNameToStringByReference(
Reference? reference,
{bool includeLibraryName = false}) {
if (reference == null) {
return '<missing-extension-type-declaration-reference>';
} else {
ExtensionTypeDeclaration? node =
reference.node as ExtensionTypeDeclaration?;
if (node != null) {
return qualifiedExtensionTypeDeclarationNameToString(node,
includeLibraryName: includeLibraryName);
} else {
CanonicalName? canonicalName = reference.canonicalName;
if (canonicalName != null) {
return qualifiedCanonicalNameToString(canonicalName,
includeLibraryName: includeLibraryName);
} else {
return '<unlinked-extension-type-declaration-reference>';
}
}
}
}
String extensionTypeDeclarationNameToString(ExtensionTypeDeclaration? node) {
return node == null ? 'null' : node.name;
}
String qualifiedTypedefNameToString(Typedef node,
{bool includeLibraryName = false}) {
TreeNode? parent = node.parent;
if (parent is Library && includeLibraryName) {
return libraryNameToString(parent) + '::' + typedefNameToString(node);
} else {
return typedefNameToString(node);
}
}
String qualifiedTypedefNameToStringByReference(Reference? reference,
{bool includeLibraryName = false}) {
if (reference == null) {
return '<missing-typedef-reference>';
} else {
Typedef? node = reference.node as Typedef?;
if (node != null) {
return qualifiedTypedefNameToString(node,
includeLibraryName: includeLibraryName);
} else {
CanonicalName? canonicalName = reference.canonicalName;
if (canonicalName != null) {
return qualifiedCanonicalNameToString(canonicalName,
includeLibraryName: includeLibraryName);
} else {
return '<unlinked-typedef-reference>';
}
}
}
}
String typedefNameToString(Typedef? node) {
return node == null ? 'null' : node.name;
}
String qualifiedMemberNameToString(Member node,
{bool includeLibraryName = false}) {
TreeNode? parent = node.parent;
if (parent is Class) {
return qualifiedClassNameToString(parent,
includeLibraryName: includeLibraryName) +
'.' +
memberNameToString(node);
} else if (parent is ExtensionTypeDeclaration) {
return qualifiedExtensionTypeDeclarationNameToString(parent,
includeLibraryName: includeLibraryName) +
'.' +
memberNameToString(node);
} else if (parent is Library && includeLibraryName) {
return libraryNameToString(parent) + '::' + memberNameToString(node);
} else {
return memberNameToString(node);
}
}
String qualifiedMemberNameToStringByReference(Reference? reference,
{bool includeLibraryName = false}) {
if (reference == null) {
return '<missing-member-reference>';
} else {
Member? node = reference.node as Member?;
if (node != null) {
return qualifiedMemberNameToString(node,
includeLibraryName: includeLibraryName);
} else {
CanonicalName? canonicalName = reference.canonicalName;
if (canonicalName != null) {
return qualifiedCanonicalNameToString(canonicalName,
includeLibraryName: includeLibraryName);
} else {
return '<unlinked-member-reference>';
}
}
}
}
String memberNameToString(Member node) {
return node.name.text;
}
String qualifiedTypeParameterNameToString(TypeParameter node,
{required bool includeLibraryName, required bool recurseOnLocalFunction}) {
GenericDeclaration? declaration = node.declaration;
String? declarationName =
_qualifiedTypeParameterGenericDeclarationNameToString(declaration,
includeLibraryName: includeLibraryName,
recurseOnLocalFunction: recurseOnLocalFunction);
if (declarationName != null) {
return "$declarationName.${typeParameterNameToString(node)}";
}
return typeParameterNameToString(node);
}
String? _qualifiedTypeParameterGenericDeclarationNameToString(
GenericDeclaration? declaration,
{required bool includeLibraryName,
required bool recurseOnLocalFunction}) {
switch (declaration) {
case Class():
return qualifiedClassNameToString(declaration,
includeLibraryName: includeLibraryName);
case Extension():
return qualifiedExtensionNameToString(declaration,
includeLibraryName: includeLibraryName);
case ExtensionTypeDeclaration():
return qualifiedExtensionTypeDeclarationNameToString(declaration,
includeLibraryName: includeLibraryName);
case Typedef():
return qualifiedTypedefNameToString(declaration,
includeLibraryName: includeLibraryName);
case Procedure():
return qualifiedMemberNameToString(declaration,
includeLibraryName: includeLibraryName);
case LocalFunction():
if (recurseOnLocalFunction &&
declaration is FunctionDeclaration &&
declaration.variable.name != null) {
TreeNode? parent = declaration.parent;
while (parent != null && parent is! GenericDeclaration) {
parent = parent.parent;
}
if (parent is GenericDeclaration) {
String? parentName =
_qualifiedTypeParameterGenericDeclarationNameToString(parent,
includeLibraryName: includeLibraryName,
recurseOnLocalFunction: recurseOnLocalFunction);
return "$parentName.${declaration.variable.name}";
}
}
return null;
case null:
return null;
}
}
String qualifiedStructuralParameterNameToString(StructuralParameter node,
{bool includeLibraryName = false}) {
return structuralParameterNameToString(node);
}
String typeParameterNameToString(TypeParameter node) {
return node.name ??
"null-named TypeParameter ${node.runtimeType} ${node.hashCode}";
}
String structuralParameterNameToString(StructuralParameter node) {
return node.name ??
"null-named StructuralParameter "
"${node.runtimeType} ${node.hashCode}";
}
String? getEscapedCharacter(int codeUnit) {
switch (codeUnit) {
case 9:
return r'\t';
case 10:
return r'\n';
case 11:
return r'\v';
case 12:
return r'\f';
case 13:
return r'\r';
case 34:
return r'\"';
case 36:
return r'\$';
case 92:
return r'\\';
default:
if (codeUnit < 32 || codeUnit > 126) {
return r'\u' + '$codeUnit'.padLeft(4, '0');
} else {
return null;
}
}
}
String escapeString(String string) {
StringBuffer? buffer;
for (int i = 0; i < string.length; ++i) {
String? character = getEscapedCharacter(string.codeUnitAt(i));
if (character != null) {
buffer ??= new StringBuffer(string.substring(0, i));
buffer.write(character);
} else {
buffer?.write(string[i]);
}
}
return buffer == null ? string : buffer.toString();
}