You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=56436
`generator` relies on the existance of a mapping from Java types to
managed types which bind the Java type. The `generator --ref` option
will cause `generator` to make this mapping based on the managed types
from an assembly, and the mapping in turn is handled by `[Register]`
and related custom attributes:
namespace Android.Runtime {
[Register ("java/util/Collection", DoNotRegisterAcw=true)]
partial class JavaCollection {
}
}
For better or worse, nothing enforces that there be only one such
mapping, It is thus possible to have multiple types partake in the
mapping process:
namespace Java.Util {
[Register ("java/util/Collection", DoNotRegisterAcw=true)]
partial interface ICollection {
}
}
A Java type is *aliased* when two or more managed types bind the same
Java type, as with the above `Android.Runtime.JavaCollection` and
`Java.Util.ICollection` types;
This is a scenario which as long existed.
Question: What does `generator` do when a type is aliased?
Answer: `generator` registers mappings from assemblies in the order of
types in the assembly it's processing. When an aliased type is found,
the *last registered type* "wins".
For example, if an assembly defines `JavaCollection` before
`ICollection`, then a type lookup for `java.util.Collection` will
return `ICollection`. If instead the assembly defines `ICollection`
before `JavaCollection`, then a type lookup for `java.util.Collection`
willl instead return `JavaCollection`.
This is not necessarily desirable, but I don't see much alternative.
Unfortunately, that's only *half* the scenario. There are a number of
situations in which `SymbolTable.Lookup()` is not given a Java name,
but is instead given the *managed binding type name*. In particular,
this happens when `ManagedClassGen.Validate()` is called, and it
attempts to validate the base class and all implemented interfaces,
using the *managed* type names for this process.
Here is where the "last registered type wins" behavior becomes
problematic, as it means that a Lookup for `Java.Util.ICollection` can
fail when `JavaCollection` is registered after `ICollection`, because
the Java name was shared.
Which brings us to Bug #56436: building a Xamarin.Android binding
project changes behavior based on whether Xamarin.Android 7.2 or
Xamarin.Android 7.3 is used, and the primary difference between these
differences is the order that types are defined in `Mono.Android.dll`.
In XA 7.2, `JavaCollection` is defined before `ICollection`.
In XA 7.3, `ICollection` is defined before `JavaCollection`.
This (subtle!) change interacts with `generator`, and within XA 7.3
means that `Java.Util.ICollection` can't be found:
warning BG8C00: For type Java.Util.AbstractQueue, base interface Java.Util.ICollection does not exist.
Improve this state of affairs by changing `SymbolTable.symbols` from a
`Dictionary<string, ISymbol>` to a `Dictionary<string, List<ISymbol>>`,
allowing `generator` to preserve all the managed types which bind a
given Java type. This in turn allows *both* `ICollection` and
`JavaCollection` to be preserved, so that a lookup for
`Java.Util.ICollection` will now work consistently, without any type
definition ordering issues.
Unfortunately lookups for the Java type `java.util.Collection` will
still be order-dependent, continuing to return the *last* registered
type. Hopefully this won't cause any problems.
0 commit comments