Class SimpleTopLevelLookup
- All Implemented Interfaces:
HierarchyAwareMappingDelegator.TopLevelMemberLookup
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)-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classA member realm is a group of class members (so either fields or methods) with the same name (but not necessarily the same descriptor or signature as it is permissible for subclasses to be more/less strict on what they return or consume) but different classes. -
Constructor Summary
ConstructorsConstructorDescriptionSimpleTopLevelLookup(@Unmodifiable @NotNull List<@NotNull org.objectweb.asm.tree.ClassNode> applicationClasses) Create aSimpleTopLevelLookupbased on a list ofClassNodesthat are used to compute the member realms.SimpleTopLevelLookup(@Unmodifiable @NotNull Map<MemberRef, SimpleTopLevelLookup.MemberRealm> realms) Create aSimpleTopLevelLookupfrom an immutable map ofmember referencesto their respectiveSimpleTopLevelLookup.MemberRealm. -
Method Summary
Modifier and TypeMethodDescription@NotNull MemberRefgetDefinition(@NotNull MemberRef reference) Obtain the root-level definition of a member.@Nullable SimpleTopLevelLookup.MemberRealmLookup theSimpleTopLevelLookup.MemberRealmof aMemberRef.static @NotNull @Unmodifiable Map<@NotNull MemberRef,@NotNull SimpleTopLevelLookup.MemberRealm> Compute a map of class member to member realm relations from a list of ClassNodes.
-
Constructor Details
-
SimpleTopLevelLookup
public SimpleTopLevelLookup(@NotNull @Unmodifiable @NotNull List<@NotNull org.objectweb.asm.tree.ClassNode> applicationClasses) Create aSimpleTopLevelLookupbased on a list ofClassNodesthat 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 aSimpleTopLevelLookupfrom an immutable map ofmember referencesto their respectiveSimpleTopLevelLookup.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 ofClassNodesto process. Members will only be in that list.- Returns:
- A
Mapthat mapsmember referencesto their respectiveSimpleTopLevelLookup.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.TopLevelMemberLookupObtain 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
MemberRefin a non-source namespace is permissible, but it is highly recommended against doing so. That being said, the inputMemberRefMUST 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:
getDefinitionin interfaceHierarchyAwareMappingDelegator.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) Lookup theSimpleTopLevelLookup.MemberRealmof aMemberRef.- Parameters:
reference- The reference to look up- Returns:
- The corresponding
MemberRef, or null if not found.
-