diff --git a/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApiTypeResolverExtensions.cs b/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApiTypeResolverExtensions.cs index af991e967..65f1ea7c7 100644 --- a/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApiTypeResolverExtensions.cs +++ b/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaApiTypeResolverExtensions.cs @@ -18,15 +18,15 @@ public static JavaTypeReference Parse (this JavaApi api, string name, params Jav var tn = JavaTypeName.Parse (name); return JavaTypeNameToReference (api, tn, contextTypeParameters); } - + static JavaTypeReference JavaTypeNameToReference (this JavaApi api, JavaTypeName tn, params JavaTypeParameters [] contextTypeParameters) { - var tp = contextTypeParameters.Where (tps => tps != null).SelectMany (tps => tps.TypeParameters).FirstOrDefault (_ => _.Name == tn.FullNameNonGeneric); + var tp = contextTypeParameters.Where (tps => tps != null).SelectMany (tps => tps.TypeParameters).FirstOrDefault (_ => _.Name == tn.DottedName); if (tp != null) return new JavaTypeReference (tp, tn.ArrayPart); - if (tn.FullNameNonGeneric == JavaTypeReference.GenericWildcard.SpecialName) + if (tn.DottedName == JavaTypeReference.GenericWildcard.SpecialName) return new JavaTypeReference (tn.BoundsType, tn.GenericConstraints?.Select (gc => JavaTypeNameToReference (api, gc, contextTypeParameters)), tn.ArrayPart); - var primitive = JavaTypeReference.GetSpecialType (tn.FullNameNonGeneric); + var primitive = JavaTypeReference.GetSpecialType (tn.DottedName); if (primitive != null) return tn.ArrayPart == null && tn.GenericConstraints == null ? primitive : new JavaTypeReference (primitive, tn.ArrayPart, tn.BoundsType, tn.GenericConstraints?.Select (gc => JavaTypeNameToReference (api, gc, contextTypeParameters))); var type = api.FindNonGenericType (tn.FullNameNonGeneric); diff --git a/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaTypeName.cs b/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaTypeName.cs index 4f7d1877e..adc9e6414 100644 --- a/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaTypeName.cs +++ b/src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaTypeName.cs @@ -33,7 +33,7 @@ public class JavaTypeName public static JavaTypeName Parse (string dottedFullName) { var ret = new JavaTypeName (); - + foreach (var label in genericConstraintsLabels) { int gcidx = dottedFullName.IndexOf (label, StringComparison.Ordinal); int gcgidx = gcidx < 0 ? -1 : dottedFullName.IndexOf ('<', 0, gcidx); @@ -45,7 +45,7 @@ public static JavaTypeName Parse (string dottedFullName) dottedFullName = dottedFullName.Substring (0, gcidx).Trim (); } } - + if (dottedFullName.EndsWith ("...", StringComparison.Ordinal)) { ret.ArrayPart = "..."; dottedFullName = dottedFullName.Substring (0, dottedFullName.Length - 3); @@ -56,36 +56,47 @@ public static JavaTypeName Parse (string dottedFullName) dottedFullName = dottedFullName.Substring (0, aidx); } - Func getMatchingGenericCloser = (str, start) => { - int count = 0; - for (int i = start; i < str.Length; i++) { - switch (str [i]) { - case '<': - count++; - break; - case '>': - if (count-- == 0) - return i; - break; - } - } - return -1; - }; int idx = dottedFullName.IndexOf ('<'); + int nextIndex = dottedFullName.Length; if (idx > 0) { - int last = getMatchingGenericCloser (dottedFullName, idx + 1); + int last = GetMatchingGenericCloser (dottedFullName, idx + 1); ret.GenericArguments = ParseCommaSeparatedTypeNames (dottedFullName.Substring (idx + 1, last - idx - 1)) .Select (s => JavaTypeName.Parse (s.Trim ())) .ToArray (); - dottedFullName = dottedFullName.Substring (0, idx); + nextIndex = last + 1; } - // at this state, there is no way to distinguish package name from this name specification. - ret.FullNameNonGeneric = dottedFullName; - + ret.DottedName = idx < 0 ? dottedFullName : dottedFullName.Substring (0, idx); + + if (nextIndex < dottedFullName.Length) { + if (dottedFullName [nextIndex] != '.') + throw new ArgumentException (nameof (dottedFullName)); + // the generic parent is parsed, but the rest is still there. + var parent = ret; + ret = Parse (dottedFullName.Substring (nextIndex + 1)); + ret.GenericParent = parent; + } + return ret; } + static int GetMatchingGenericCloser (string str, int start) + { + int count = 0; + for (int i = start; i < str.Length; i++) { + switch (str [i]) { + case '<': + count++; + break; + case '>': + if (count-- == 0) + return i; + break; + } + } + return -1; + } + static IEnumerable ParseCommaSeparatedTypeNames (string args) { int comma = args.IndexOf (','); @@ -119,11 +130,22 @@ static IEnumerable ParseCommaSeparatedTypeNames (string args) } } } - - public string FullNameNonGeneric { get; set; } + + public JavaTypeName GenericParent { get; set; } + public string DottedName { get; set; } public string BoundsType { get; set; } // " extends " / " super " public IList GenericConstraints { get; private set; } public IList GenericArguments { get; private set; } public string ArrayPart { get; set; } + + public string FullNameNonGeneric { + get { + if (GenericParent != null) + return GenericParent.FullNameNonGeneric + "." + DottedName; + else + return DottedName; + } + } + } } diff --git a/src/Xamarin.Android.Tools.ApiXmlAdjuster/Tests/JavaApiTest.cs b/src/Xamarin.Android.Tools.ApiXmlAdjuster/Tests/JavaApiTest.cs index bc66871d3..edf26b42e 100644 --- a/src/Xamarin.Android.Tools.ApiXmlAdjuster/Tests/JavaApiTest.cs +++ b/src/Xamarin.Android.Tools.ApiXmlAdjuster/Tests/JavaApiTest.cs @@ -42,6 +42,22 @@ public void ParseName () Assert.AreEqual (1, ga2.GenericConstraints.Count, "genarg#1 incorrect number of parsed generic constraints"); Assert.AreEqual ("U", ga2.GenericConstraints [0].FullNameNonGeneric, "genarg#1.1 constraint name mismatch"); } + + [Test] + public void ParseName2 () + { + string name = "com.good.gd.ndkproxy.auth.GDFingerprintAuthenticationManager.a.b"; + var tn = JavaTypeName.Parse (name); + Assert.IsTrue (tn.GenericParent != null, "result has generic parent"); + Assert.AreEqual ("b", tn.DottedName, "result name mismatch"); + Assert.AreEqual ("com.good.gd.ndkproxy.auth.GDFingerprintAuthenticationManager.a.b", tn.FullNameNonGeneric, "failed to parse name"); + Assert.AreEqual (1, tn.GenericArguments.Count, "result genparams count mismatch"); + Assert.AreEqual ("com.good.gd.ndkproxy.auth.d.a", tn.GenericArguments [0].FullNameNonGeneric, "result genarg name mismatch"); + var p = tn.GenericParent; + Assert.AreEqual (1, p.GenericArguments.Count, "top genparams count"); + var ga1 = p.GenericArguments [0]; + Assert.AreEqual ("com.good.gd.ndkproxy.auth.c.a", ga1.FullNameNonGeneric, "top genarg name mismatch"); + } } }