Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
70 changes: 46 additions & 24 deletions src/Xamarin.Android.Tools.ApiXmlAdjuster/JavaTypeName.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -56,36 +56,47 @@ public static JavaTypeName Parse (string dottedFullName)
dottedFullName = dottedFullName.Substring (0, aidx);
}

Func<string, int, int> 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<string> ParseCommaSeparatedTypeNames (string args)
{
int comma = args.IndexOf (',');
Expand Down Expand Up @@ -119,11 +130,22 @@ static IEnumerable<string> 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<JavaTypeName> GenericConstraints { get; private set; }
public IList<JavaTypeName> GenericArguments { get; private set; }
public string ArrayPart { get; set; }

public string FullNameNonGeneric {
get {
if (GenericParent != null)
return GenericParent.FullNameNonGeneric + "." + DottedName;
else
return DottedName;
}
}

}
}
16 changes: 16 additions & 0 deletions src/Xamarin.Android.Tools.ApiXmlAdjuster/Tests/JavaApiTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<com.good.gd.ndkproxy.auth.c.a>.b<com.good.gd.ndkproxy.auth.d.a>";
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");
}
}
}