// 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.library_index;

import 'ast.dart';

/// Provides name-based access to library, class, and member AST nodes.
///
/// When constructed, a given set of libraries are indexed immediately, and
/// will not be up-to-date with changes made after it was created.
class LibraryIndex {
  static const String getterPrefix = 'get:';
  static const String setterPrefix = 'set:';
  static const String tearoffPrefix = 'get#';

  /// A special class name that can be used to access the top-level members
  /// of a library.
  static const String topLevel = '::';

  final Map<String, _ClassTable> _libraries = <String, _ClassTable>{};

  /// Indexes the libraries with the URIs given in [libraryUris].
  LibraryIndex(Component component, Iterable<String> libraryUris)
      : this.fromLibraries(component.libraries, libraryUris);

  /// Indexes the libraries with the URIs given in [libraryUris].
  LibraryIndex.fromLibraries(
      Iterable<Library> libraries, Iterable<String> libraryUris) {
    Set<String> libraryUriSet = libraryUris.toSet();
    for (Library library in libraries) {
      String uri = '${library.importUri}';
      if (libraryUriSet.contains(uri)) {
        _libraries[uri] = new _ClassTable(library);
      }
    }
  }

  /// Indexes the libraries with the URIs given in [libraryUris].
  LibraryIndex.byUri(Component component, Iterable<Uri> libraryUris)
      : this(component, libraryUris.map((uri) => '$uri'));

  /// Indexes `dart:` libraries.
  LibraryIndex.coreLibraries(Component component) {
    for (Library library in component.libraries) {
      if (library.importUri.isScheme('dart')) {
        _libraries['${library.importUri}'] = new _ClassTable(library);
      }
    }
  }

  /// Indexes the entire component.
  ///
  /// Consider using another constructor to only index the libraries that
  /// are needed.
  LibraryIndex.all(Component component) {
    for (Library library in component.libraries) {
      _libraries['${library.importUri}'] = new _ClassTable(library);
    }
  }

  _ClassTable _getLibraryIndex(String uri) {
    _ClassTable? libraryIndex = _libraries[uri];
    if (libraryIndex == null) {
      throw "The library '$uri' has not been indexed";
    }
    return libraryIndex;
  }

  /// Returns the library with the given URI.
  ///
  /// Throws an error if it does not exist.
  Library getLibrary(String uri) => _getLibraryIndex(uri).library;

  /// Like [getLibrary] but returns `null` if not found.
  Library? tryGetLibrary(String uri) => _libraries[uri]?.library;

  /// True if the library with the given URI exists and was indexed.
  bool containsLibrary(String uri) => _libraries.containsKey(uri);

  /// Returns the class with the given name in the given library.
  ///
  /// An error is thrown if the class is not found.
  Class getClass(String library, String className) {
    return _getLibraryIndex(library).getClass(className);
  }

  /// Like [getClass] but returns `null` if not found.
  Class? tryGetClass(String library, String className) {
    return _libraries[library]?.tryGetClass(className);
  }

  /// Returns the member with the given name, in the given class, in the
  /// given library.
  ///
  /// If a getter or setter is wanted, the `get:` or `set:` prefix must be
  /// added in front of the member name.
  ///
  /// The special class name `::` can be used to access top-level members.
  ///
  /// If the member name is private it is considered private to [library].
  /// It is not possible with this class to lookup members whose name is private
  /// to a library other than the one containing it.
  ///
  /// An error is thrown if the member is not found.
  Member getMember(String library, String className, String memberName) {
    return _getLibraryIndex(library).getMember(className, memberName);
  }

  /// Like [getMember] but returns `null` if not found.
  Member? tryGetMember(String library, String className, String memberName) {
    return _libraries[library]?.tryGetMember(className, memberName);
  }

  Constructor getConstructor(
      String library, String className, String memberName) {
    return _getLibraryIndex(library).getConstructor(className, memberName);
  }

  Procedure getProcedure(String library, String className, String memberName) {
    return _getLibraryIndex(library).getProcedure(className, memberName);
  }

  Field getField(String library, String className, String memberName) {
    return _getLibraryIndex(library).getField(className, memberName);
  }

  /// Returns the top-level member with the given name, in the given library.
  ///
  /// If a getter or setter is wanted, the `get:` or `set:` prefix must be
  /// added in front of the member name.
  ///
  /// If the member name is private it is considered private to [library].
  /// It is not possible with this class to lookup members whose name is private
  /// to a library other than the one containing it.
  ///
  /// An error is thrown if the member is not found.
  Member getTopLevelMember(String library, String memberName) {
    return getMember(library, topLevel, memberName);
  }

  /// Like [getTopLevelMember] but returns `null` if not found.
  Member? tryGetTopLevelMember(String library, String memberName) {
    return tryGetMember(library, topLevel, memberName);
  }

  Procedure getTopLevelProcedure(String library, String memberName) {
    return getProcedure(library, topLevel, memberName);
  }

  Field getTopLevelField(String library, String memberName) {
    return getField(library, topLevel, memberName);
  }
}

class _ClassTable {
  final Library library;

  Map<String, _MemberTable>? _classes;

  _ClassTable(this.library);

  Map<String, _MemberTable> get classes {
    if (_classes == null) {
      _classes = <String, _MemberTable>{};
      _classes![LibraryIndex.topLevel] = new _MemberTable.topLevel(this);
      for (Class class_ in library.classes) {
        _classes![class_.name] = new _MemberTable.fromClass(this, class_);
      }
      for (Extension extension_ in library.extensions) {
        _classes![extension_.name] =
            new _MemberTable.fromExtension(this, extension_);
      }
      for (Reference reference in library.additionalExports) {
        NamedNode? node = reference.node;
        if (node is Class) {
          _classes![node.name] = new _MemberTable.fromClass(this, node);
        } else if (node is Extension) {
          _classes![node.name] = new _MemberTable.fromExtension(this, node);
        }
      }
    }
    return _classes!;
  }

  String get containerName {
    return "library '${library.importUri}'";
  }

  _MemberTable _getClassIndex(String name) {
    _MemberTable? indexer = classes[name];
    if (indexer == null) {
      throw "Class '$name' not found in $containerName";
    }
    return indexer;
  }

  Class getClass(String name) {
    return _getClassIndex(name).class_!;
  }

  Class? tryGetClass(String name) {
    return classes[name]?.class_;
  }

  Member getMember(String className, String memberName) {
    return _getClassIndex(className).getMember(memberName);
  }

  Member? tryGetMember(String className, String memberName) {
    return classes[className]?.tryGetMember(memberName);
  }

  Constructor getConstructor(String className, String memberName) {
    return _getClassIndex(className).getConstructor(memberName);
  }

  Procedure getProcedure(String className, String memberName) {
    return _getClassIndex(className).getProcedure(memberName);
  }

  Field getField(String className, String memberName) {
    return _getClassIndex(className).getField(memberName);
  }
}

class _MemberTable {
  final _ClassTable parent;
  final Class? class_; // Null for top-level or extension.
  final Extension? extension_; // Null for top-level or class.
  Map<String, Member>? _members;

  Library get library => parent.library;

  _MemberTable.fromClass(this.parent, this.class_) : extension_ = null;
  _MemberTable.fromExtension(this.parent, this.extension_) : class_ = null;
  _MemberTable.topLevel(this.parent)
      : class_ = null,
        extension_ = null;

  Map<String, Member> get members {
    if (_members == null) {
      _members = <String, Member>{};
      if (class_ != null) {
        class_!.procedures.forEach(_addMember);
        class_!.fields.forEach(_addMember);
        class_!.constructors.forEach(_addMember);
      } else if (extension_ != null) {
        extension_!.members.forEach(_addExtensionMember);
      } else {
        library.procedures.forEach(_addMember);
        library.fields.forEach(_addMember);
      }
    }
    return _members!;
  }

  String getDisambiguatedName(Member member) {
    if (member is Procedure) {
      if (member.isGetter) return LibraryIndex.getterPrefix + member.name.text;
      if (member.isSetter) return LibraryIndex.setterPrefix + member.name.text;
    }
    return member.name.text;
  }

  void _addMember(Member member) {
    if (member.name.isPrivate && member.name.library != library) {
      // Members whose name is private to other libraries cannot currently
      // be found with the LibraryIndex class.
      return;
    }
    _members![getDisambiguatedName(member)] = member;
  }

  String getDisambiguatedExtensionName(
      ExtensionMemberDescriptor extensionMember) {
    if (extensionMember.kind == ExtensionMemberKind.TearOff) {
      return LibraryIndex.tearoffPrefix + extensionMember.name.text;
    }
    if (extensionMember.kind == ExtensionMemberKind.Getter) {
      return LibraryIndex.getterPrefix + extensionMember.name.text;
    }
    if (extensionMember.kind == ExtensionMemberKind.Setter) {
      return LibraryIndex.setterPrefix + extensionMember.name.text;
    }
    return extensionMember.name.text;
  }

  void _addExtensionMember(ExtensionMemberDescriptor extensionMember) {
    final NamedNode? replacement = extensionMember.member.node;
    if (replacement is! Member) return;
    Member member = replacement;
    if (member.name.isPrivate && member.name.library != library) {
      // Members whose name is private to other libraries cannot currently
      // be found with the LibraryIndex class.
      return;
    }

    final String name = getDisambiguatedExtensionName(extensionMember);
    _members![name] = replacement;
  }

  String get containerName {
    if (class_ != null) {
      return "class '${class_!.name}' in ${parent.containerName}";
    } else if (extension_ != null) {
      return "extension '${extension_!.name}' in ${parent.containerName}";
    } else {
      return "top-level of ${parent.containerName}";
    }
  }

  Member getMember(String name) {
    Member? member = members[name];
    if (member == null) {
      String message = "A member with disambiguated name '$name' was not found "
          "in $containerName";
      String getter = LibraryIndex.getterPrefix + name;
      String setter = LibraryIndex.setterPrefix + name;
      if (members[getter] != null || members[setter] != null) {
        throw "$message. Did you mean '$getter' or '$setter'?";
      }
      throw message;
    }
    return member;
  }

  Member? tryGetMember(String name) => members[name];

  Constructor getConstructor(String name) {
    Member member = getMember(name);
    if (member is! Constructor) {
      throw "Member '$name' in $containerName is not a Constructor: "
          "${member} (${member.runtimeType}).";
    }
    return member;
  }

  Procedure getProcedure(String name) {
    Member member = getMember(name);
    if (member is! Procedure) {
      throw "Member '$name' in $containerName is not a Procedure: "
          "${member} (${member.runtimeType}).";
    }
    return member;
  }

  Field getField(String name) {
    Member member = getMember(name);
    if (member is! Field) {
      throw "Member '$name' in $containerName is not a Field: "
          "${member} (${member.runtimeType}).";
    }
    return member;
  }
}
