Class SimpleTopLevelLookup

java.lang.Object
org.stianloader.remapper.SimpleTopLevelLookup
All Implemented Interfaces:
HierarchyAwareMappingDelegator.TopLevelMemberLookup

public class SimpleTopLevelLookup extends Object implements HierarchyAwareMappingDelegator.TopLevelMemberLookup
An implementation of HierarchyAwareMappingDelegator.TopLevelMemberLookup that works based on a statically computed map of MemberRef to SimpleTopLevelLookup.MemberRealm. The SimpleTopLevelLookup.MemberRealm can be used to obtain the realm members, that is the uses of a realm or the types where the member can be used in (note that in cases where two interfaces define the same method, the set of realm members may overlap - at this point in time there is no good approach of handling that edge-case besides praying it does not occur). A SimpleTopLevelLookup.MemberRealm also documents the root definition of a member (in case of the interface edge case, this is by default the most frequently implemented interface - if both interfaces are implemented the same amount of times, it falls back to lexicographic ordering)
  • Constructor Details

    • SimpleTopLevelLookup

      public SimpleTopLevelLookup(@NotNull @Unmodifiable @NotNull List<@NotNull org.objectweb.asm.tree.ClassNode> applicationClasses)
      Create a SimpleTopLevelLookup based on a list of ClassNodes that are used to compute the member realms.

      JDK Classes or library classes that are irrelevant to the remapping process should be left out for performance (especially memory-related) reasons.

      Parameters:
      applicationClasses - The list of classes to analyze
    • SimpleTopLevelLookup

      public SimpleTopLevelLookup(@NotNull @Unmodifiable @NotNull Map<MemberRef,SimpleTopLevelLookup.MemberRealm> realms)
      Create a SimpleTopLevelLookup from an immutable map of member references to their respective SimpleTopLevelLookup.MemberRealm.

      JDK Classes or library classes that are irrelevant to the remapping process should be left out for performance (especially memory-related) reasons.

      Parameters:
      realms - The map to use to lookup the realm of members.
  • Method Details

    • realmsOf

      @NotNull public static @NotNull @Unmodifiable Map<@NotNull MemberRef,@NotNull SimpleTopLevelLookup.MemberRealm> realmsOf(@NotNull @Unmodifiable @NotNull List<@NotNull org.objectweb.asm.tree.ClassNode> nodes)
      Compute a map of class member to member realm relations from a list of ClassNodes.

      The classnodes within the list should include everything that is relevant to the remapping process - so the obfuscated application as well optionally the application that needs to be remapped (e.g. when remapping mods).

      However, one currently known edge-case (technically a bug) is that when two interfaces define a method with the same name and descriptor, then if the method hierarchies were to intersect, then the method realms would still be treated separately, even though in reality they are the same realm.

      Parameters:
      nodes - The list of ClassNodes to process. Members will only be in that list.
      Returns:
      A Map that maps member references to their respective SimpleTopLevelLookup.MemberRealm.
    • getDefinition

      @NotNull @Contract(pure=true, value="!null -> !null; null -> fail") @NonBlocking public @NotNull MemberRef getDefinition(@NotNull @NotNull MemberRef reference)
      Description copied from interface: HierarchyAwareMappingDelegator.TopLevelMemberLookup
      Obtain the root-level definition of a member.

      Beware that this method may be called for fields and static methods, too. It is imperative that the declaration of fields is also followed as it is possible for javac to emit GETFIELD and PUTFIELD requests where the owner does not match the class where the field in question is defined - this for example might be produced by anonymous enum members.

      Implementors are free to handle bridge methods as they please - the only requirement is that they do it persistently and that implementors should be aware that this would cause the bridge methods to potentially have the same name as the method it bridges to. This interface does not mandate any behaviour towards bridge methods and they may be ignored completely (this most likely won't have any notable repercussions anyways unless the codebase in question uses a lot of generics - however, generics are likely to be absent anyways in which case searching for bridge methods may be a bit superfluous).

      Changing the computational type of the descriptor of the member is not permitted and will result in an exception being thrown in HierarchyAwareMappingDelegator.remapMember(MemberRef, String). However, outside of that changing the descriptor of a method is permitted, as might for example be needed for bridge methods.

      Implementations should return the original source reference for classes or methods they do not know. Under rare cases it is possible for methods to change their descriptor in the JRE, so this fact shouldn't be ignored even if the implementation should handle JRE classes (this specification recommends against handling inheritance beyond the application that needs to be remapped).

      Returning a MemberRef in a non-source namespace is permissible, but it is highly recommended against doing so. That being said, the input MemberRef MUST be in the source namespace.

      Performance

      Stianloader-remapper expects calls to this method to be non-blocking and quick to process. Thus implementors should use caching if appropriate as it is reasonable to expect that this method will be called multiple times (sometimes even consecutively) with the same input argument - even if the returned value should be the same across all calls.
      Specified by:
      getDefinition in interface HierarchyAwareMappingDelegator.TopLevelMemberLookup
      Parameters:
      reference - The reference of the member in the source namespace.
      Returns:
      The reference of the declaration of the member
    • realmOf

      @Nullable @Contract(pure=true) public @Nullable SimpleTopLevelLookup.MemberRealm realmOf(@NotNull @NotNull MemberRef reference)
      Parameters:
      reference - The reference to look up
      Returns:
      The corresponding MemberRef, or null if not found.