diff --git a/src/Xamarin.Android.Tools.Bytecode/Methods.cs b/src/Xamarin.Android.Tools.Bytecode/Methods.cs index 13cd56b18..c8a7eef08 100644 --- a/src/Xamarin.Android.Tools.Bytecode/Methods.cs +++ b/src/Xamarin.Android.Tools.Bytecode/Methods.cs @@ -93,6 +93,7 @@ public ParameterInfo[] GetParameters () UpdateParametersFromMethodParametersAttribute (parameters); return parameters; } + static IEnumerable ExtractTypesFromSignature (string signature) { if (signature == null || signature.Length < "()V".Length) @@ -106,6 +107,7 @@ static IEnumerable ExtractTypesFromSignature (string signature) yield return Signature.ExtractType (signature, ref index); } } + List GetParametersFromDescriptor (out int endParams) { var signature = Descriptor; @@ -165,43 +167,18 @@ void UpdateParametersFromLocalVariables (ParameterInfo[] parameters) return; var names = locals.LocalVariables.Where (p => p.StartPC == 0).ToList (); - int namesStart = 0; - if (!AccessFlags.HasFlag (MethodAccessFlags.Static) && - names.Count > namesStart && - names [namesStart].Descriptor == DeclaringType.FullJniName) { - namesStart++; // skip `this` parameter - } - if (!DeclaringType.IsStatic && - IsConstructor && - names.Count > namesStart && - DeclaringType.InnerClass != null && DeclaringType.InnerClass.OuterClassName != null && - names [namesStart].Descriptor == "L" + DeclaringType.InnerClass.OuterClassName + ";") { - namesStart++; // "outer `this`", for non-static inner classes - } - if (!DeclaringType.IsStatic && - IsConstructor && - names.Count > namesStart && - DeclaringType.TryGetEnclosingMethodInfo (out var declaringClass, out var _, out var _) && - names [namesStart].Descriptor == "L" + declaringClass + ";") { - namesStart++; // "outer `this`", for non-static inner classes - } - - // For JvmOverloadsConstructor..(LJvmOverloadsConstructor;IILjava/lang/String;)V - if (namesStart > 0 && - names.Count > namesStart && - parameters.Length > 0 && - names [namesStart].Descriptor != parameters [0].Type.BinaryName && - names [namesStart-1].Descriptor == parameters [0].Type.BinaryName) { - namesStart--; - } int parametersCount = GetDeclaredParametersCount (parameters); - CheckDescriptorVariablesToLocalVariables (parameters, parametersCount, names, namesStart); - int max = Math.Min (parametersCount, names.Count - namesStart); - for (int i = 0; i < max; ++i) { - parameters [i].Name = names [namesStart+i].Name; - CheckLocalVariableTypeToDescriptorType (i, parameters, names, namesStart); + for (int pi = parametersCount-1; pi >= 0; --pi) { + for (int ni = names.Count-1; ni >= 0; --ni) { + if (parameters [pi].Type.BinaryName != names [ni].Descriptor) { + continue; + } + parameters [pi].Name = names [ni].Name; + names.RemoveAt (ni); + break; + } } } @@ -273,60 +250,6 @@ void UpdateParametersFromSignature (ParameterInfo[] parameters) } } - void CheckDescriptorVariablesToLocalVariables (ParameterInfo[] parameters, int parametersCount, List names, int namesStart) - { - if (AccessFlags.HasFlag (MethodAccessFlags.Synthetic)) - return; - if ((names.Count - namesStart) == parametersCount) - return; - if (IsEnumCtor) - return; - - var paramsDesc = CreateParametersList (parameters, (v, i) => $"`{v.Type.BinaryName}` {v.Name}{(i >= parametersCount ? " /* abi; ignored */" : "")}"); - var localsDesc = CreateParametersList (names, (v, i) => $"`{v.Descriptor}` {v.Name}{(i < namesStart ? " /* abi; skipped */" : "")}"); - - Log.Debug ($"class-parse: method {DeclaringType.ThisClass.Name.Value}.{Name}.{Descriptor}: namesStart={namesStart}; " + - $"Local variables array has {names.Count - namesStart} entries {localsDesc}; " + - $"descriptor has {parametersCount} entries {paramsDesc}!"); - } - - static string CreateParametersList(IEnumerable values, Func createElement) - { - var description = new StringBuilder () - .Append ("("); - - int index = 0; - var first = true; - foreach (var v in values) { - if (!first) { - description.Append (", "); - } - first = false; - description.Append (createElement (v, index)); - index++; - } - description.Append (")"); - - return description.ToString (); - } - - void CheckLocalVariableTypeToDescriptorType (int index, ParameterInfo[] parameters, List names, int namesStart) - { - if (AccessFlags.HasFlag (MethodAccessFlags.Synthetic)) - return; - - var parameterType = parameters [index].Type.BinaryName; - var descriptorType = names [index + namesStart].Descriptor; - if (parameterType == descriptorType) - return; - - var paramsDesc = CreateParametersList (parameters, (v, i) => $"`{v.Type.BinaryName}` {v.Name}"); - var localsDesc = CreateParametersList (names, (v, i) => $"`{v.Descriptor}` {v.Name}{(i < namesStart ? " /* abi; skipped */" : "")}"); - - Log.Debug ($"class-parse: method {DeclaringType.ThisClass.Name.Value}.{Name}.{Descriptor}: " + - $"Local variables array {localsDesc} element {index+namesStart} with type `{descriptorType}` doesn't match expected descriptor list {paramsDesc} element {index} with type `{parameterType}`."); - } - void CheckDescriptorVariablesToSignatureParameters (ParameterInfo[] parameters, int parametersCount, MethodTypeSignature sig) { if (IsEnumCtor) diff --git a/tests/Xamarin.Android.Tools.Bytecode-Tests/JavaTypeNoParametersTests.cs b/tests/Xamarin.Android.Tools.Bytecode-Tests/JavaTypeNoParametersTests.cs new file mode 100644 index 000000000..46a3aea2c --- /dev/null +++ b/tests/Xamarin.Android.Tools.Bytecode-Tests/JavaTypeNoParametersTests.cs @@ -0,0 +1,45 @@ +using System; + +using Xamarin.Android.Tools.Bytecode; + +using NUnit.Framework; + +namespace Xamarin.Android.Tools.BytecodeTests { + + [TestFixture] + public class JavaTypeNoParametersTests : ClassFileFixture { + + const string JavaType = "JavaTypeNoParameters"; + + [Test] + public void ClassFile_WithNonGenericGlobalType_class () + { + var c = LoadClassFile (JavaType + ".class"); + new ExpectedTypeDeclaration { + MajorVersion = 0x34, + MinorVersion = 0, + ConstantPoolCount = 18, + AccessFlags = ClassAccessFlags.Public | ClassAccessFlags.Super, + FullName = "com/xamarin/JavaTypeNoParameters", + Superclass = new TypeInfo ("java/lang/Object", "Ljava/lang/Object;"), + Methods = { + new ExpectedMethodDeclaration { + Name = "", + AccessFlags = MethodAccessFlags.Public, + ReturnDescriptor = "V", + Parameters = { + new ParameterInfo ("copy", "Lcom/xamarin/JavaTypeNoParameters;", "Lcom/xamarin/JavaTypeNoParameters;"), + }, + }, + } + }.Assert (c); + } + + [Test] + public void XmlDeclaration_WithNonGenericGlobalType_class () + { + AssertXmlDeclaration (JavaType + ".class", JavaType + ".xml"); + } + } +} + diff --git a/tests/Xamarin.Android.Tools.Bytecode-Tests/Resources/JavaTypeNoParameters.xml b/tests/Xamarin.Android.Tools.Bytecode-Tests/Resources/JavaTypeNoParameters.xml new file mode 100644 index 000000000..da8a05312 --- /dev/null +++ b/tests/Xamarin.Android.Tools.Bytecode-Tests/Resources/JavaTypeNoParameters.xml @@ -0,0 +1,34 @@ + + + + + + + + + diff --git a/tests/Xamarin.Android.Tools.Bytecode-Tests/Xamarin.Android.Tools.Bytecode-Tests.csproj b/tests/Xamarin.Android.Tools.Bytecode-Tests/Xamarin.Android.Tools.Bytecode-Tests.csproj index 0601462d4..406e03ede 100644 --- a/tests/Xamarin.Android.Tools.Bytecode-Tests/Xamarin.Android.Tools.Bytecode-Tests.csproj +++ b/tests/Xamarin.Android.Tools.Bytecode-Tests/Xamarin.Android.Tools.Bytecode-Tests.csproj @@ -38,6 +38,7 @@ + diff --git a/tests/Xamarin.Android.Tools.Bytecode-Tests/Xamarin.Android.Tools.Bytecode-Tests.targets b/tests/Xamarin.Android.Tools.Bytecode-Tests/Xamarin.Android.Tools.Bytecode-Tests.targets index f28e526f7..50b0895a9 100644 --- a/tests/Xamarin.Android.Tools.Bytecode-Tests/Xamarin.Android.Tools.Bytecode-Tests.targets +++ b/tests/Xamarin.Android.Tools.Bytecode-Tests/Xamarin.Android.Tools.Bytecode-Tests.targets @@ -1,15 +1,21 @@ - - + + + + + <_BuildClassOutputs Include="@(TestJar->'$(IntermediateOutputPath)classes\%(RecursiveDir)%(Filename).class')" /> + <_BuildClassOutputs Include="@(TestJarNoParameters->'$(IntermediateOutputPath)classes\%(RecursiveDir)%(Filename).class')" /> + + + Inputs="@(TestJar);@(TestJarNoParameters)" + Outputs="@(_BuildClassOutputs)"> diff --git a/tests/Xamarin.Android.Tools.Bytecode-Tests/java/com/xamarin/JavaTypeNoParameters.java b/tests/Xamarin.Android.Tools.Bytecode-Tests/java/com/xamarin/JavaTypeNoParameters.java new file mode 100644 index 000000000..6cda34be6 --- /dev/null +++ b/tests/Xamarin.Android.Tools.Bytecode-Tests/java/com/xamarin/JavaTypeNoParameters.java @@ -0,0 +1,9 @@ +package com.xamarin; + +public class JavaTypeNoParameters { + /** + * JNI sig: (Lcom/xamarin/JavaTypeNoParameters;)V + */ + public JavaTypeNoParameters (JavaTypeNoParameters copy) { + } +}