This improves the output significantly - by merging in more cases, we
avoid the need to use suffixes (e.g. srcOff2, srcOff3, etc. in the
ArrayUtils class) for what is really the same variable.
Restricting the merging to scopes contained in another prevents variable
declarations for two distinct variables sharing a local variable index
from being lifted outside of an if/else block. This often prevents us
from being able to combine a series of if/else blocks into a longer
change, thus increasing the indentation level.
Revert part of a change introduced upstream. 81faff674c (diff-e057d0d70e5b15f5e12ec86ac46c85eeR57)
This upstream change causes local variables to not be inlined in many cases, and makes decomp very messy for the reason of 'thread safety'.
The previous implementation simply returned java/lang/Object when given
two object types, which resulted in local object variables assigned in
more than one place being given a type of java/lang/Object. The
variables often had ugly casts wherever they were used.
The new implementation is from ASM's ClassWriter.
I think the EXPRENT_FIELD condition exists in case the field's
initializer depends on a prior field in the same class.
We already handle this case in the deobfuscator, which ensures fields
appear in exactly the order in which they are first written to in the
<init> and <clinit> methods. (This isn't perfect, as we ignore the
problem of multiple <init> methods writing fields in different orders to
each other, but it seems good enough for the client.)
I think it's best not to conflate this with visibleOffset, as
visibleOffset is not always set to bytecode_offset and it is also used
for other things (e.g. looking up debug variable names).
This isn't perfect. It doesn't handle stack variables yet. I think there
are also some places where Fernflower fiddles around with VarExprents
where we'll need to copy the bytecode offset.