Virtual renaming
Description
Virtual renaming is supporting mappings that are not actually globally applied to the inputs. When a user has virtual mappings and they decompile a class, it is filtered through a renamer with the virtual mappings before the decompiler looks at the bytecode. This allows the renamer to replace any mapped references.
The user can opt to actually apply these virtual mappings at any point, and in doing so they lose their "virtual" aspect since they are actually applied to the bytecode of classes in the workspace.
Possible Implementation
In the 3.X branch all class fetching is done through Resources.get(name). The name is the internal name of a class in the workspace. We can wrap it in getVirtual(name) which checks if the name is one that belongs to a virtual mapping. If so, then it will call get(name) with the key for the mapping. If it is not a virtual mapping value, then it just calls get(name) normally.
The actual return value of get(name) is a ClassInfo wrapper. We can create a copy of it with details that are updated to reflect the value of the virtual mappings. For instance get("Apple") can return a ClassInfo whose name is Orange if we have a mapping of Apple -> Orange. Any field and method types are also updated to reflect these mappings.
The Tricky Part
If we follow the implementation details above, then consider what would happen if we attempt to open the assembler of some method's bytecode. Do we want the original class bytecode or the virtual mapped bytecode? Clearly we want to work in the virtual mapped context, but we need to make sure our compilations still target the original name. So following our Apple -> Orange example we want to be able to have INVOKEVIRTUAL Apple.eat() transformed into INVOKEVIRTUAL Orange.eat() before being assembled.
Any location where a class name, or field/method type is shown will also need to make sure to use the virtual mapped name. If it is interactive it must be able to look up the original name so context sensitive behavior still relates to the original class/field/method.
Working around the tricky part
If we create a package dedicated to virtual renaming/mapping we can create an API that any component can implement to largely automate the process of having to accommodate reverse mapping and other issues.