diff --git a/src/test/fixtures/README.md b/src/test/fixtures/README.md index 3a6a6a9..812d30f 100644 --- a/src/test/fixtures/README.md +++ b/src/test/fixtures/README.md @@ -345,3 +345,18 @@ Compiled with Scala 2.11.5 under Java 8, `-target:jvm-1.8`, against the untouche | --- | --- | | `ReferenceScalaAppliedTypeDescriptor` | `40eebab873311f3fec01dd5678e1c12c3af959b7f357aa49ed9cca59e1889b99` | | `ReferenceScalaAppliedTypeDescriptor$$anon$1` | `0ac784d966048b6daa6715ead62360624a22d6a0927aba280c6d3908de11447e` | + +### `ReferenceScalaClassSymbolFull` + +`scala/codechicken/multipart/compat/ReferenceScalaClassSymbolFull.scala` freezes a Scala caller and direct +ClassSymbolRef implementation. Tests use it to preserve the old trait helper, virtual owner/name reads and failures. + +Compiled with Scala 2.11.5 under Java 8, `-target:jvm-1.8`, against the untouched dev jar at `24c7723` +(SHA-256 `40c5851ad982190b2f44cd7473d8fb3ab73e0dc3d3bfa2911de06b924532248d`). Source SHA-256 is +`3744035617fbe0a1619d20ae2a44259e9aea9ea3dfa16d19a1c9b57daef0ffee`. Frozen class files are under +`src/test/resources/compat/`; do not regenerate them against the port. + +| Class | SHA-256 | +| --- | --- | +| `ReferenceScalaClassSymbolFull` | `77498a049a18080a67b557b1751c7f8ab905b9f832ebd680db822e5447ea0799` | +| `ReferenceScalaClassSymbolFull$$anon$1` | `df9d4c907de922b6e917ea848e40f746ef446bf601dbda4b8d9f9761403b5f46` | diff --git a/src/test/fixtures/scala/codechicken/multipart/compat/ReferenceScalaClassSymbolFull.scala b/src/test/fixtures/scala/codechicken/multipart/compat/ReferenceScalaClassSymbolFull.scala new file mode 100644 index 0000000..eeb1c1a --- /dev/null +++ b/src/test/fixtures/scala/codechicken/multipart/compat/ReferenceScalaClassSymbolFull.scala @@ -0,0 +1,20 @@ +package codechicken.multipart.compat + +import java.util.function.Supplier + +import codechicken.multipart.asm.ScalaSignature + +class ReferenceScalaClassSymbolFull { + def ref( + sig: ScalaSignature, + owners: Supplier[ScalaSignature#SymbolRef], + names: Supplier[String] + ): ScalaSignature#ClassSymbolRef = new sig.ClassSymbolRef { + def name = names.get() + def owner = owners.get().asInstanceOf[sig.SymbolRef] + def flags = 0 + def infoId = 0 + } + + def full(ref: ScalaSignature#ClassSymbolRef): String = ref.full +} diff --git a/src/test/java/codechicken/multipart/asm/ScalaSignatureClassSymbolFullTest.java b/src/test/java/codechicken/multipart/asm/ScalaSignatureClassSymbolFullTest.java new file mode 100644 index 0000000..2296334 --- /dev/null +++ b/src/test/java/codechicken/multipart/asm/ScalaSignatureClassSymbolFullTest.java @@ -0,0 +1,220 @@ +package codechicken.multipart.asm; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.InputStream; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Proxy; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import java.util.Objects; +import java.util.Scanner; +import java.util.function.Supplier; + +import org.junit.jupiter.api.Test; + +import codechicken.multipart.asm.ScalaSignature.Bytes; +import codechicken.multipart.asm.ScalaSignature.ClassSymbolRef; +import codechicken.multipart.asm.ScalaSignature.SymbolRef; + +class ScalaSignatureClassSymbolFullTest { + + private static final Fixture FIXTURE = new Fixture(); + + @Test + void concreteClassAndObjectSymbolsJoinTheirOwnerAndName() { + ScalaSignature sig = signature(); + assertEquals("pkg.Owner.Name", sig.new ClassSymbol("Name", sig.new ExternalSymbol("pkg.Owner"), 0, 0).full()); + assertEquals(".Module", sig.new ObjectSymbol("Module", sig.NoSymbol(), 0, 0).full()); + assertEquals("..a,b(c)", sig.new ClassSymbol("a,b(c)", sig.new ExternalSymbol("."), 0, 0).full()); + } + + @Test + void nullFullNameAndNameAreFormattedLiterally() { + ScalaSignature sig = signature(); + SymbolRef nullFull = sig.new ExternalSymbol("unused") { + + @Override + public String full() { + return null; + } + }; + assertEquals("null.Name", sig.new ClassSymbol("Name", nullFull, 0, 0).full()); + assertEquals("pkg.Owner.null", sig.new ClassSymbol(null, sig.new ExternalSymbol("pkg.Owner"), 0, 0).full()); + } + + @Test + void frozenScalaImplementorReadsOwnerFullAndNameInOrderOnEveryQuery() throws Throwable { + ScalaSignature sig = signature(); + List calls = new ArrayList<>(); + int[] query = { 0 }; + SymbolRef owner = sig.new ExternalSymbol("unused") { + + @Override + public String full() { + calls.add("owner.full"); + return "Owner" + query[0]; + } + }; + ClassSymbolRef ref = ref(sig, () -> { + calls.add("owner"); + return owner; + }, () -> { + calls.add("name"); + return "Name" + query[0]++; + }); + assertEquals("Owner0.Name0", full(ref)); + assertEquals("Owner1.Name1", full(ref)); + assertEquals(Arrays.asList("owner", "owner.full", "name", "owner", "owner.full", "name"), calls); + } + + @Test + void failuresStopAtTheSelectedOwnerOrNameRead() throws Throwable { + ScalaSignature sig = signature(); + List order = Arrays.asList("owner", "owner.full", "name"); + RuntimeException failure = new IllegalStateException("class symbol full getter"); + for (String failing : order) { + List calls = new ArrayList<>(); + SymbolRef owner = sig.new ExternalSymbol("unused") { + + @Override + public String full() { + return read(calls, "owner.full", "Owner", failing, failure); + } + }; + ClassSymbolRef ref = ref( + sig, + () -> read(calls, "owner", owner, failing, failure), + () -> read(calls, "name", "Name", failing, failure)); + assertSame(failure, assertThrows(RuntimeException.class, () -> full(ref))); + assertEquals(order.subList(0, order.indexOf(failing) + 1), calls); + } + } + + @Test + void nullOwnerFailsBeforeReadingTheName() throws Throwable { + ScalaSignature sig = signature(); + int[] nameReads = { 0 }; + ClassSymbolRef ref = ref(sig, () -> null, () -> { + nameReads[0]++; + return "Name"; + }); + assertThrows(NullPointerException.class, () -> full(ref)); + assertEquals(0, nameReads[0]); + } + + @Test + void fullDoesNotReadOwnerStringOrOtherSymbolMembers() { + ScalaSignature sig = signature(); + SymbolRef owner = sig.new ExternalSymbol("Owner") { + + @Override + public String toString() { + throw new AssertionError("owner.toString"); + } + }; + ClassSymbolRef ref = sig.new ClassSymbol("Name", owner, 0, 0) { + + @Override + public int flags() { + throw new AssertionError("flags"); + } + + @Override + public int infoId() { + throw new AssertionError("infoId"); + } + + @Override + public String toString() { + throw new AssertionError("toString"); + } + }; + assertEquals("Owner.Name", ref.full()); + } + + @Test + void legacyStaticTraitBridgeKeepsItsDescriptorAndNullReceiverFailure() throws Throwable { + MethodHandle bridge = MethodHandles.lookup().findStatic( + Class.forName("codechicken.multipart.asm.ScalaSignature$ClassSymbolRef$class"), + "full", + MethodType.methodType(String.class, ClassSymbolRef.class)); + ScalaSignature sig = signature(); + List calls = new ArrayList<>(); + SymbolRef owner = sig.new ExternalSymbol("unused") { + + @Override + public String full() { + calls.add("owner.full"); + return "Owner"; + } + }; + ClassSymbolRef ref = (ClassSymbolRef) Proxy.newProxyInstance( + ClassSymbolRef.class.getClassLoader(), + new Class[] { ClassSymbolRef.class }, + (proxy, method, args) -> { + calls.add(method.getName()); + if (method.getName().equals("owner")) return owner; + if (method.getName().equals("name")) return "Name"; + throw new AssertionError(method.getName()); + }); + assertEquals("Owner.Name", (String) bridge.invokeExact(ref)); + assertEquals(Arrays.asList("owner", "owner.full", "name"), calls); + assertThrows(NullPointerException.class, () -> bridge.invokeWithArguments(new Object[] { null })); + } + + private static T read(List calls, String name, T value, String failing, RuntimeException failure) { + calls.add(name); + if (name.equals(failing)) throw failure; + return value; + } + + private static ClassSymbolRef ref(ScalaSignature sig, Supplier owners, Supplier names) + throws Throwable { + return (ClassSymbolRef) FIXTURE.ref.invoke(sig, owners, names); + } + + private static String full(ClassSymbolRef ref) throws Throwable { + return (String) FIXTURE.full.invoke(ref); + } + + private static ScalaSignature signature() { + return new ScalaSignature(new Bytes(new byte[] { 5, 0, 0 }, 0, 3)); + } + + private static final class Fixture extends ClassLoader { + + final MethodHandle ref; + final MethodHandle full; + + Fixture() { + super(ScalaSignatureClassSymbolFullTest.class.getClassLoader()); + try { + String base = "ReferenceScalaClassSymbolFull"; + for (String suffix : new String[] { "", "$$anon$1" }) { + byte[] bytes; + try (InputStream stream = Objects + .requireNonNull(getResourceAsStream("compat/" + base + suffix + ".class.b64")); + Scanner scanner = new Scanner(stream, StandardCharsets.UTF_8.name()).useDelimiter("\\A")) { + bytes = Base64.getMimeDecoder().decode(scanner.next()); + } + defineClass(null, bytes, 0, bytes.length); + } + Class type = loadClass("codechicken.multipart.compat." + base); + Object instance = type.getConstructor().newInstance(); + ref = MethodHandles.publicLookup() + .unreflect(type.getMethod("ref", ScalaSignature.class, Supplier.class, Supplier.class)) + .bindTo(instance); + full = MethodHandles.publicLookup().unreflect(type.getMethod("full", ClassSymbolRef.class)) + .bindTo(instance); + } catch (ReflectiveOperationException | java.io.IOException e) { + throw new AssertionError(e); + } + } + } +} diff --git a/src/test/resources/compat/ReferenceScalaClassSymbolFull$$anon$1.class.b64 b/src/test/resources/compat/ReferenceScalaClassSymbolFull$$anon$1.class.b64 new file mode 100644 index 0000000..963295b --- /dev/null +++ b/src/test/resources/compat/ReferenceScalaClassSymbolFull$$anon$1.class.b64 @@ -0,0 +1,86 @@ +yv66vgAAADQAnQEAQmNvZGVjaGlja2VuL211bHRpcGFydC9jb21wYXQvUmVmZXJlbmNlU2NhbGFD +bGFzc1N5bWJvbEZ1bGwkJGFub24kMQcAAQEAEGphdmEvbGFuZy9PYmplY3QHAAMBADdjb2RlY2hp +Y2tlbi9tdWx0aXBhcnQvYXNtL1NjYWxhU2lnbmF0dXJlJENsYXNzU3ltYm9sUmVmBwAFAQAjUmVm +ZXJlbmNlU2NhbGFDbGFzc1N5bWJvbEZ1bGwuc2NhbGEBADpjb2RlY2hpY2tlbi9tdWx0aXBhcnQv +Y29tcGF0L1JlZmVyZW5jZVNjYWxhQ2xhc3NTeW1ib2xGdWxsBwAIAQADcmVmAQCfKExjb2RlY2hp +Y2tlbi9tdWx0aXBhcnQvYXNtL1NjYWxhU2lnbmF0dXJlO0xqYXZhL3V0aWwvZnVuY3Rpb24vU3Vw +cGxpZXI7TGphdmEvdXRpbC9mdW5jdGlvbi9TdXBwbGllcjspTGNvZGVjaGlja2VuL211bHRpcGFy +dC9hc20vU2NhbGFTaWduYXR1cmUkQ2xhc3NTeW1ib2xSZWY7DAAKAAsBAAVzaWckMQEAKkxjb2Rl +Y2hpY2tlbi9tdWx0aXBhcnQvYXNtL1NjYWxhU2lnbmF0dXJlOwEACG93bmVycyQxAQAdTGphdmEv +dXRpbC9mdW5jdGlvbi9TdXBwbGllcjsBAAduYW1lcyQxAQAEZnVsbAEAFCgpTGphdmEvbGFuZy9T +dHJpbmc7AQA9Y29kZWNoaWNrZW4vbXVsdGlwYXJ0L2FzbS9TY2FsYVNpZ25hdHVyZSRDbGFzc1N5 +bWJvbFJlZiRjbGFzcwcAFAEATShMY29kZWNoaWNrZW4vbXVsdGlwYXJ0L2FzbS9TY2FsYVNpZ25h +dHVyZSRDbGFzc1N5bWJvbFJlZjspTGphdmEvbGFuZy9TdHJpbmc7DAASABYKABUAFwEABHRoaXMB +AERMY29kZWNoaWNrZW4vbXVsdGlwYXJ0L2NvbXBhdC9SZWZlcmVuY2VTY2FsYUNsYXNzU3ltYm9s +RnVsbCQkYW5vbiQxOwEACHRvU3RyaW5nDAAbABYKABUAHAEACGlzT2JqZWN0AQADKClaAQA8KExj +b2RlY2hpY2tlbi9tdWx0aXBhcnQvYXNtL1NjYWxhU2lnbmF0dXJlJENsYXNzU3ltYm9sUmVmOyla +DAAeACAKABUAIQEABGluZm8BADYoKUxjb2RlY2hpY2tlbi9tdWx0aXBhcnQvYXNtL1NjYWxhU2ln +bmF0dXJlJENsYXNzVHlwZTsBAG8oTGNvZGVjaGlja2VuL211bHRpcGFydC9hc20vU2NhbGFTaWdu +YXR1cmUkQ2xhc3NTeW1ib2xSZWY7KUxjb2RlY2hpY2tlbi9tdWx0aXBhcnQvYXNtL1NjYWxhU2ln +bmF0dXJlJENsYXNzVHlwZTsMACMAJQoAFQAmAQAHalBhcmVudAwAKAAWCgAVACkBAAtqSW50ZXJm +YWNlcwEAIygpTHNjYWxhL2NvbGxlY3Rpb24vaW1tdXRhYmxlL0xpc3Q7AQBcKExjb2RlY2hpY2tl +bi9tdWx0aXBhcnQvYXNtL1NjYWxhU2lnbmF0dXJlJENsYXNzU3ltYm9sUmVmOylMc2NhbGEvY29s +bGVjdGlvbi9pbW11dGFibGUvTGlzdDsMACsALQoAFQAuAQAHaGFzRmxhZwEABChJKVoBADhjb2Rl +Y2hpY2tlbi9tdWx0aXBhcnQvYXNtL1NjYWxhU2lnbmF0dXJlJFN5bWJvbFJlZiRjbGFzcwcAMgEA +OChMY29kZWNoaWNrZW4vbXVsdGlwYXJ0L2FzbS9TY2FsYVNpZ25hdHVyZSRTeW1ib2xSZWY7SSla +DAAwADQKADMANQEABGZsYWcBAAFJAQAJaXNQcml2YXRlAQA0Y29kZWNoaWNrZW4vbXVsdGlwYXJ0 +L2FzbS9TY2FsYVNpZ25hdHVyZSRGbGFncyRjbGFzcwcAOgEAMyhMY29kZWNoaWNrZW4vbXVsdGlw +YXJ0L2FzbS9TY2FsYVNpZ25hdHVyZSRGbGFnczspWgwAOQA8CgA7AD0BAAtpc1Byb3RlY3RlZAwA +PwA8CgA7AEABAAppc0Fic3RyYWN0DABCADwKADsAQwEACmlzRGVmZXJyZWQMAEUAPAoAOwBGAQAI +aXNNZXRob2QMAEgAPAoAOwBJAQAIaXNNb2R1bGUMAEsAPAoAOwBMAQALaXNJbnRlcmZhY2UMAE4A +PAoAOwBPAQAHaXNQYXJhbQwAUQA8CgA7AFIBAAhpc1N0YXRpYwwAVAA8CgA7AFUBAAdpc1RyYWl0 +DABXADwKADsAWAEACmlzQWNjZXNzb3IMAFoAPAoAOwBbAQAEbmFtZQwAEQAQCQACAF4BABtqYXZh +L3V0aWwvZnVuY3Rpb24vU3VwcGxpZXIHAGABAANnZXQBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwwA +YgBjCwBhAGQBABBqYXZhL2xhbmcvU3RyaW5nBwBmAQAFb3duZXIBADYoKUxjb2RlY2hpY2tlbi9t +dWx0aXBhcnQvYXNtL1NjYWxhU2lnbmF0dXJlJFN5bWJvbFJlZjsMAA8AEAkAAgBqAQAyY29kZWNo +aWNrZW4vbXVsdGlwYXJ0L2FzbS9TY2FsYVNpZ25hdHVyZSRTeW1ib2xSZWYHAGwBAAVmbGFncwEA +AygpSQEABmluZm9JZAEAP2NvZGVjaGlja2VuJG11bHRpcGFydCRhc20kU2NhbGFTaWduYXR1cmUk +Q2xhc3NTeW1ib2xSZWYkJCRvdXRlcgEALCgpTGNvZGVjaGlja2VuL211bHRpcGFydC9hc20vU2Nh +bGFTaWduYXR1cmU7DAANAA4JAAIAcwEAOmNvZGVjaGlja2VuJG11bHRpcGFydCRhc20kU2NhbGFT +aWduYXR1cmUkU3ltYm9sUmVmJCQkb3V0ZXIBAAY8aW5pdD4BAKMoTGNvZGVjaGlja2VuL211bHRp +cGFydC9jb21wYXQvUmVmZXJlbmNlU2NhbGFDbGFzc1N5bWJvbEZ1bGw7TGNvZGVjaGlja2VuL211 +bHRpcGFydC9hc20vU2NhbGFTaWduYXR1cmU7TGphdmEvdXRpbC9mdW5jdGlvbi9TdXBwbGllcjtM +amF2YS91dGlsL2Z1bmN0aW9uL1N1cHBsaWVyOylWAQADKClWDAB2AHgKAAQAeQEABiRpbml0JAEA +MyhMY29kZWNoaWNrZW4vbXVsdGlwYXJ0L2FzbS9TY2FsYVNpZ25hdHVyZSRGbGFnczspVgwAewB8 +CgA7AH0BADcoTGNvZGVjaGlja2VuL211bHRpcGFydC9hc20vU2NhbGFTaWduYXR1cmUkU3ltYm9s +UmVmOylWDAB7AH8KADMAgAEAPChMY29kZWNoaWNrZW4vbXVsdGlwYXJ0L2FzbS9TY2FsYVNpZ25h +dHVyZSRDbGFzc1N5bWJvbFJlZjspVgwAewCCCgAVAIMBAAYkb3V0ZXIBADxMY29kZWNoaWNrZW4v +bXVsdGlwYXJ0L2NvbXBhdC9SZWZlcmVuY2VTY2FsYUNsYXNzU3ltYm9sRnVsbDsBAC5jb2RlY2hp +Y2tlbi9tdWx0aXBhcnQvYXNtL1NjYWxhU2lnbmF0dXJlJEZsYWdzBwCHAQAoY29kZWNoaWNrZW4v +bXVsdGlwYXJ0L2FzbS9TY2FsYVNpZ25hdHVyZQcAiQEABUZsYWdzAQAyY29kZWNoaWNrZW4vbXVs +dGlwYXJ0L2FzbS9TY2FsYVNpZ25hdHVyZSRDbGFzc1R5cGUHAIwBAAlDbGFzc1R5cGUBAAlTeW1i +b2xSZWYBAAtGbGFncyRjbGFzcwEADkNsYXNzU3ltYm9sUmVmAQAPU3ltYm9sUmVmJGNsYXNzAQAU +Q2xhc3NTeW1ib2xSZWYkY2xhc3MBAARDb2RlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAPTGluZU51 +bWJlclRhYmxlAQAJU2lnbmF0dXJlAQA3KClMc2NhbGEvY29sbGVjdGlvbi9pbW11dGFibGUvTGlz +dDxMamF2YS9sYW5nL1N0cmluZzs+OwEAClNvdXJjZUZpbGUBAA9FbmNsb3NpbmdNZXRob2QBAAxJ +bm5lckNsYXNzZXMBAAVTY2FsYQAxAAIABAABAAYAAwASAA0ADgAAABIADwAQAAAAEgARABAAAAAZ +AAEAEgATAAEAlAAAAC8AAQABAAAABSq4ABiwAAAAAgCVAAAADAABAAAABQAZABoAAACWAAAABgAB +AAAADAABABsAEwABAJQAAAAvAAEAAQAAAAUquAAdsAAAAAIAlQAAAAwAAQAAAAUAGQAaAAAAlgAA +AAYAAQAAAAwAAQAeAB8AAQCUAAAALwABAAEAAAAFKrgAIqwAAAACAJUAAAAMAAEAAAAFABkAGgAA +AJYAAAAGAAEAAAAMAAEAIwAkAAEAlAAAAC8AAQABAAAABSq4ACewAAAAAgCVAAAADAABAAAABQAZ +ABoAAACWAAAABgABAAAADAABACgAEwABAJQAAAAvAAEAAQAAAAUquAAqsAAAAAIAlQAAAAwAAQAA +AAUAGQAaAAAAlgAAAAYAAQAAAAwAAQArACwAAgCUAAAALwABAAEAAAAFKrgAL7AAAAACAJUAAAAM +AAEAAAAFABkAGgAAAJYAAAAGAAEAAAAMAJcAAAACAJgAAQAwADEAAQCUAAAAOgACAAIAAAAGKhu4 +ADasAAAAAgCVAAAAFgACAAAABgAZABoAAAAAAAYANwA4AAEAlgAAAAYAAQAAAAwAAQA5AB8AAQCU +AAAALwABAAEAAAAFKrgAPqwAAAACAJUAAAAMAAEAAAAFABkAGgAAAJYAAAAGAAEAAAAMAAEAPwAf +AAEAlAAAAC8AAQABAAAABSq4AEGsAAAAAgCVAAAADAABAAAABQAZABoAAACWAAAABgABAAAADAAB +AEIAHwABAJQAAAAvAAEAAQAAAAUquABErAAAAAIAlQAAAAwAAQAAAAUAGQAaAAAAlgAAAAYAAQAA +AAwAAQBFAB8AAQCUAAAALwABAAEAAAAFKrgAR6wAAAACAJUAAAAMAAEAAAAFABkAGgAAAJYAAAAG +AAEAAAAMAAEASAAfAAEAlAAAAC8AAQABAAAABSq4AEqsAAAAAgCVAAAADAABAAAABQAZABoAAACW +AAAABgABAAAADAABAEsAHwABAJQAAAAvAAEAAQAAAAUquABNrAAAAAIAlQAAAAwAAQAAAAUAGQAa +AAAAlgAAAAYAAQAAAAwAAQBOAB8AAQCUAAAALwABAAEAAAAFKrgAUKwAAAACAJUAAAAMAAEAAAAF +ABkAGgAAAJYAAAAGAAEAAAAMAAEAUQAfAAEAlAAAAC8AAQABAAAABSq4AFOsAAAAAgCVAAAADAAB +AAAABQAZABoAAACWAAAABgABAAAADAABAFQAHwABAJQAAAAvAAEAAQAAAAUquABWrAAAAAIAlQAA +AAwAAQAAAAUAGQAaAAAAlgAAAAYAAQAAAAwAAQBXAB8AAQCUAAAALwABAAEAAAAFKrgAWawAAAAC +AJUAAAAMAAEAAAAFABkAGgAAAJYAAAAGAAEAAAAMAAEAWgAfAAEAlAAAAC8AAQABAAAABSq4AFys +AAAAAgCVAAAADAABAAAABQAZABoAAACWAAAABgABAAAADAABAF0AEwABAJQAAAA3AAEAAQAAAA0q +tABfuQBlAQDAAGewAAAAAgCVAAAADAABAAAADQAZABoAAACWAAAABgABAAAADQABAGgAaQABAJQA +AAA3AAEAAQAAAA0qtABruQBlAQDAAG2wAAAAAgCVAAAADAABAAAADQAZABoAAACWAAAABgABAAAA +DgABAG4AbwABAJQAAAAsAAEAAQAAAAIDrAAAAAIAlQAAAAwAAQAAAAIAGQAaAAAAlgAAAAYAAQAA +AA8AAQBwAG8AAQCUAAAALAABAAEAAAACA6wAAAACAJUAAAAMAAEAAAACABkAGgAAAJYAAAAGAAEA +AAAQEAEAcQByAAEAlAAAACMAAQABAAAABSq0AHSwAAAAAQCVAAAADAABAAAABQAZABoAABABAHUA +cgABAJQAAAAjAAEAAQAAAAUqtAB0sAAAAAEAlQAAAAwAAQAAAAUAGQAaAAAAAQB2AHcAAQCUAAAA +cwACAAUAAAAhKiy1AHQqLbUAayoZBLUAXyq3AHoquAB+KrgAgSq4AISxAAAAAgCVAAAANAAFAAAA +IQAZABoAAAAAACEAhQCGAAEAAAAhAA0ADgACAAAAIQAPABAAAwAAACEAEQAQAAQAlgAAAAYAAQAA +AAwABACZAAAAAgAHAJoAAAAEAAkADACbAAAAQgAIAIgAigCLBgkAjQCKAI4AAQBtAIoAjwYBADsA +igCQBAkABgCKAJEGAQAzAIoAkgQBABUAigCTBAEAAgAAAAAAEQCcAAAAAA== \ No newline at end of file diff --git a/src/test/resources/compat/ReferenceScalaClassSymbolFull.class.b64 b/src/test/resources/compat/ReferenceScalaClassSymbolFull.class.b64 new file mode 100644 index 0000000..44b3f68 --- /dev/null +++ b/src/test/resources/compat/ReferenceScalaClassSymbolFull.class.b64 @@ -0,0 +1,40 @@ +yv66vgAAADQALwEAOmNvZGVjaGlja2VuL211bHRpcGFydC9jb21wYXQvUmVmZXJlbmNlU2NhbGFD +bGFzc1N5bWJvbEZ1bGwHAAEBABBqYXZhL2xhbmcvT2JqZWN0BwADAQAjUmVmZXJlbmNlU2NhbGFD +bGFzc1N5bWJvbEZ1bGwuc2NhbGEBAB5Mc2NhbGEvcmVmbGVjdC9TY2FsYVNpZ25hdHVyZTsBAAVi +eXRlcwEBywYBATNBIQECARMJaSIrGjRmZRZ0Ny1aKmRDMgw3CVwxdGdOS1hOWThtDVZkR04DAgQJ +BTExbVw3cUNSVCEhAgQCEzUsSA5eNXFDSiQoIkEEAhcNfEctWjJpUw5cV01cAgEnCQEhAgUCDB01 +CUFCQwEOAxUZOC0ZN2ITCXlBQgEEQl1mFFZNGgUGIwEhCUFFAQd5JXQXDh4gFQNNASIBBgEOAwlB +UUEGAQUCXQkxQV0zZykRQRJlCRoRBWV5AkMBDh4bBVkiQgEPBQMNCTcvXAUDPW0RYWJVMmJZBhwW +bho4YmlWFFgtAwIhOwlxMQlcMXRnTktYTlk4bSUWNAciAhIWAQRJEmFBOmpPIilBJQZhAUsFMXFu +HjhmZU4EMkFKFzAbBTkjQgEVKgMhMVdPXDJ1Uz50J0IBFiwDESlILxs3CwMxCkFBWzF3QyYRYWYK +AgknVgQID1w1ZmVCEREETQUDY3UREWJVPW5FPmQnKxo0CQtNKgIZARsCCzkMVy5aOhEHGWpTBwUC +N3M5ETFiTgUDcTEJYQEVOmZJFjQXQgEePAUZGUZPXTVvTyoRAQgEBQZ7ASEJQVABBU1WZEcOBgI2 +fyEpYQMQYQExAQEAA3JlZgEAnyhMY29kZWNoaWNrZW4vbXVsdGlwYXJ0L2FzbS9TY2FsYVNpZ25h +dHVyZTtMamF2YS91dGlsL2Z1bmN0aW9uL1N1cHBsaWVyO0xqYXZhL3V0aWwvZnVuY3Rpb24vU3Vw +cGxpZXI7KUxjb2RlY2hpY2tlbi9tdWx0aXBhcnQvYXNtL1NjYWxhU2lnbmF0dXJlJENsYXNzU3lt +Ym9sUmVmOwEAQmNvZGVjaGlja2VuL211bHRpcGFydC9jb21wYXQvUmVmZXJlbmNlU2NhbGFDbGFz +c1N5bWJvbEZ1bGwkJGFub24kMQcACwEABjxpbml0PgEAoyhMY29kZWNoaWNrZW4vbXVsdGlwYXJ0 +L2NvbXBhdC9SZWZlcmVuY2VTY2FsYUNsYXNzU3ltYm9sRnVsbDtMY29kZWNoaWNrZW4vbXVsdGlw +YXJ0L2FzbS9TY2FsYVNpZ25hdHVyZTtMamF2YS91dGlsL2Z1bmN0aW9uL1N1cHBsaWVyO0xqYXZh +L3V0aWwvZnVuY3Rpb24vU3VwcGxpZXI7KVYMAA0ADgoADAAPAQAEdGhpcwEAPExjb2RlY2hpY2tl +bi9tdWx0aXBhcnQvY29tcGF0L1JlZmVyZW5jZVNjYWxhQ2xhc3NTeW1ib2xGdWxsOwEAA3NpZwEA +Kkxjb2RlY2hpY2tlbi9tdWx0aXBhcnQvYXNtL1NjYWxhU2lnbmF0dXJlOwEABm93bmVycwEAHUxq +YXZhL3V0aWwvZnVuY3Rpb24vU3VwcGxpZXI7AQAFbmFtZXMBAARmdWxsAQBNKExjb2RlY2hpY2tl +bi9tdWx0aXBhcnQvYXNtL1NjYWxhU2lnbmF0dXJlJENsYXNzU3ltYm9sUmVmOylMamF2YS9sYW5n +L1N0cmluZzsBADdjb2RlY2hpY2tlbi9tdWx0aXBhcnQvYXNtL1NjYWxhU2lnbmF0dXJlJENsYXNz +U3ltYm9sUmVmBwAaAQAUKClMamF2YS9sYW5nL1N0cmluZzsMABgAHAsAGwAdAQA5TGNvZGVjaGlj +a2VuL211bHRpcGFydC9hc20vU2NhbGFTaWduYXR1cmUkQ2xhc3NTeW1ib2xSZWY7AQADKClWDAAN +ACAKAAQAIQEAKGNvZGVjaGlja2VuL211bHRpcGFydC9hc20vU2NhbGFTaWduYXR1cmUHACMBAA5D +bGFzc1N5bWJvbFJlZgEABENvZGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAA9MaW5lTnVtYmVyVGFi +bGUBAAlTaWduYXR1cmUBAOkoTGNvZGVjaGlja2VuL211bHRpcGFydC9hc20vU2NhbGFTaWduYXR1 +cmU7TGphdmEvdXRpbC9mdW5jdGlvbi9TdXBwbGllcjxMY29kZWNoaWNrZW4vbXVsdGlwYXJ0L2Fz +bS9TY2FsYVNpZ25hdHVyZSRTeW1ib2xSZWY7PjtMamF2YS91dGlsL2Z1bmN0aW9uL1N1cHBsaWVy +PExqYXZhL2xhbmcvU3RyaW5nOz47KUxjb2RlY2hpY2tlbi9tdWx0aXBhcnQvYXNtL1NjYWxhU2ln +bmF0dXJlJENsYXNzU3ltYm9sUmVmOwEAClNvdXJjZUZpbGUBAAxJbm5lckNsYXNzZXMBABlSdW50 +aW1lVmlzaWJsZUFubm90YXRpb25zAQAIU2NhbGFTaWcAIQACAAQAAAAAAAMAAQAJAAoAAgAmAAAA +VAAGAAQAAAAMuwAMWSorLC23ABCwAAAAAgAnAAAAKgAEAAAADAARABIAAAAAAAwAEwAUAAEAAAAM +ABUAFgACAAAADAAXABYAAwAoAAAABgABAAAADAApAAAAAgAqAAEAGAAZAAEAJgAAADsAAQACAAAA +Byu5AB4BALAAAAACACcAAAAWAAIAAAAHABEAEgAAAAAABwAJAB8AAQAoAAAABgABAAAAEwABAA0A +IAABACYAAAAvAAEAAQAAAAUqtwAisQAAAAIAJwAAAAwAAQAAAAUAEQASAAAAKAAAAAYAAQAAABQA +BAArAAAAAgAFACwAAAASAAIAGwAkACUGAQAMAAAAAAARAC0AAAALAAEABgABAAdzAAgALgAAAAMF +AAA= \ No newline at end of file