Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4565369

Browse files
jpobstjonpryor
authored andcommitted
[generator] Improve generic type lookup (#552)
Fixes: #543 In commit 262743b we began stripping the arity from Cecil imported types so that we wouldn't write invalid types like ``System.Collections.Generic.IList`1<string>``, in order to correctly emit `System.Collections.Generic.IList<string>`. However when we try to resolve these types in the `SymbolTable` we only look at the type name, ignoring the generic type parameters. In this case we are looking for `System.Collections.Generic.IList` but the type is stored in the symbol table with the arity to disambiguate types like ``Action`1`` and ``Action`2``. Therefore our lookup fails because the table key is ``System.Collections.Generic.IList`1``. For example, if we have `LibraryA.dll` with: public class Foo : Java.Lang.Object { public virtual void Bar (IList<string> p0) {…} } And we attempt to bind a `LibraryB.jar` which references `LibraryA.dll`, overriding `Foo.Bar()`: public class Foo2 : Foo { public override void Bar (IList<string> p0) {…} } Then `Foo2.Bar()` would elicit a BG8800 warning: warning BG8800: Unknown parameter type System.Collections.Generic.IList<System.String> in method Bar in managed type Foo2. Fix type lookup so that if the type is not found in the `SymbolTable` and there are generic type parameters, calculate the arity from the generic type parameters and look in the table again. That is, `System.Collections.Generic.IList<string>` is rechecked as ``System.Collections.Generic.IList`1``, which allows the type to be found.
1 parent 71afce5 commit 4565369

File tree

2 files changed

+75
-2
lines changed

2 files changed

+75
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using MonoDroid.Generation;
3+
using NUnit.Framework;
4+
5+
namespace generatortests
6+
{
7+
[TestFixture]
8+
public class SymbolTableTests
9+
{
10+
[Test]
11+
public void FindGenericTypes ()
12+
{
13+
var table = new SymbolTable ();
14+
15+
var list = new InterfaceGen (new GenBaseSupport {
16+
Name = "System.Collections.Generic.IList`1",
17+
FullName = "System.Collections.Generic.IList`1",
18+
JavaSimpleName = "System.Collections.Generic.IList`1"
19+
});
20+
21+
table.AddType (list);
22+
23+
var dict = new InterfaceGen (new GenBaseSupport {
24+
Name = "System.Collections.Generic.IDictionary`2",
25+
FullName = "System.Collections.Generic.IDictionary`2",
26+
JavaSimpleName = "System.Collections.Generic.IDictionary`2"
27+
});
28+
29+
table.AddType (dict);
30+
31+
Assert.AreEqual ("System.Collections.Generic.IList`1", table.Lookup ("System.Collections.Generic.IList<Java.Util.Locale.LanguageRange>").FullName);
32+
Assert.AreEqual ("System.Collections.Generic.IList`1", table.Lookup ("System.Collections.Generic.IList<List<Java.Util.Locale.LanguageRange>>").FullName);
33+
34+
Assert.AreEqual ("System.Collections.Generic.IDictionary`2", table.Lookup ("System.Collections.Generic.IDictionary<string, Java.Util.Locale.LanguageRange>").FullName);
35+
Assert.AreEqual ("System.Collections.Generic.IDictionary`2", table.Lookup ("System.Collections.Generic.IDictionary<string, List<Java.Util.Locale.LanguageRange>>").FullName);
36+
37+
Assert.AreEqual ("System.Collections.Generic.IList`1", table.Lookup ("System.Collections.Generic.IList<Dictionary<string, Java.Util.Locale.LanguageRange>>").FullName);
38+
}
39+
}
40+
}

tools/generator/Java.Interop.Tools.Generator.ObjectModel/Symbols/SymbolTable.cs

+35-2
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,15 @@ public ISymbol Lookup (string java_type)
268268
if (all_symbols_cache == null)
269269
all_symbols_cache = new ConcurrentDictionary<string, ISymbol> (symbols.Values.SelectMany (v => v).GroupBy (s => s.FullName).ToDictionary (s => s.Key, s => s.FirstOrDefault ()));
270270

271-
all_symbols_cache.TryGetValue (key, out sym);
271+
if (!all_symbols_cache.TryGetValue (key, out sym)) {
272+
// We may be looking for a type like:
273+
// - System.Collections.Generic.IList<Java.Util.Locale.LanguageRange>
274+
// Our key is "System.Collections.Generic.IList", but it's stored in
275+
// the symbol table with the arity so we need to look for
276+
// "System.Collections.Generic.IList`1" to find a match
277+
key = AddArity (key, type_params);
278+
all_symbols_cache.TryGetValue (key, out sym);
279+
}
272280
}
273281
}
274282
ISymbol result;
@@ -298,7 +306,32 @@ public ISymbol Lookup (string java_type)
298306

299307
return result;
300308
}
301-
309+
310+
private string AddArity (string key, string typeParams)
311+
{
312+
if (string.IsNullOrWhiteSpace (typeParams) || !typeParams.StartsWith ("<") || !typeParams.EndsWith (">"))
313+
return key;
314+
315+
var nested_count = 0;
316+
var arity = 1;
317+
318+
// Remove the outer <>
319+
typeParams = typeParams.Substring (1, typeParams.Length - 2);
320+
321+
foreach (var c in typeParams) {
322+
if (c == '>')
323+
nested_count--;
324+
325+
if (c == '<')
326+
nested_count++;
327+
328+
if (nested_count == 0 && c == ',')
329+
arity++;
330+
}
331+
332+
return $"{key}`{arity}";
333+
}
334+
302335
public void Dump ()
303336
{
304337
foreach (var p in symbols) {

0 commit comments

Comments
 (0)