125 lines
4.3 KiB
C#
125 lines
4.3 KiB
C#
|
|
namespace system.reflection
|
|
{
|
|
|
|
public static class FSharpCompat
|
|
{
|
|
|
|
// we don't yet translate .Net attributes to Java annotations,
|
|
// so we have to fake some attributes to support F# ToString()
|
|
|
|
public static object[] GetCustomAttributes_Type(java.lang.Class scanClass,
|
|
java.lang.Class attrClass)
|
|
{
|
|
// we manufacture a CompilationMapping attribute for a type
|
|
// type implements at least three specific interfaces.
|
|
// if it has a nested Tags class, it is a (discriminated union)
|
|
// SumType; otherwise it is a plain RecordType.
|
|
|
|
if (IsFSharpAttr(attrClass) && IsFSharpType(scanClass))
|
|
{
|
|
int sourceConstructFlags = IsFSharpSumType(scanClass)
|
|
? /* SumType */ 1 : /* RecordType */ 2;
|
|
|
|
return CreateAttr(attrClass, sourceConstructFlags);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
|
|
|
|
public static object[] GetCustomAttributes_Property(java.lang.Class declClass,
|
|
java.lang.Class attrClass)
|
|
{
|
|
if (IsFSharpAttr(attrClass))
|
|
{
|
|
// we manufacture a CompilationMapping attribute for a property:
|
|
// - if declared directly in a class that is an "F# type"
|
|
// and is not also a SumType
|
|
// - if declared in an inner class, and the outer class
|
|
// is an "F# type" that is a SumType
|
|
|
|
bool isFSharp = IsFSharpType(declClass);
|
|
if (isFSharp)
|
|
{
|
|
if (IsFSharpSumType(declClass))
|
|
isFSharp = false;
|
|
}
|
|
else
|
|
{
|
|
var outerClass = declClass.getDeclaringClass();
|
|
if (outerClass != null)
|
|
isFSharp = IsFSharpType(outerClass);
|
|
}
|
|
|
|
if (isFSharp)
|
|
{
|
|
return CreateAttr(attrClass, /* Field */ 4);
|
|
}
|
|
|
|
return RuntimeType.EmptyObjectArray;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
private static bool IsFSharpType(java.lang.Class scanClass)
|
|
{
|
|
int requiredInterfaceCount = 0;
|
|
foreach (var ifc in scanClass.getInterfaces())
|
|
{
|
|
if ( ifc == (java.lang.Class)
|
|
typeof(System.Collections.IStructuralEquatable)
|
|
|| ifc == (java.lang.Class)
|
|
typeof(System.Collections.IStructuralComparable)
|
|
|| ifc == (java.lang.Class) typeof(System.IComparable))
|
|
requiredInterfaceCount++;
|
|
}
|
|
return (requiredInterfaceCount >= 3);
|
|
}
|
|
|
|
|
|
private static bool IsFSharpSumType(java.lang.Class scanClass)
|
|
=> system.RuntimeType.FindInnerClass(scanClass, "Tags") != null;
|
|
|
|
|
|
private static bool IsFSharpAttr(java.lang.Class attrClass)
|
|
=> attrClass == (java.lang.Class)
|
|
typeof(Microsoft.FSharp.Core.CompilationMappingAttribute);
|
|
|
|
|
|
private static object[] CreateAttr(java.lang.Class attrClass,
|
|
int sourceConstructFlags)
|
|
{
|
|
foreach (var _constr in attrClass.getConstructors())
|
|
{
|
|
#pragma warning disable 0436
|
|
var constr = (java.lang.reflect.Constructor) (object) _constr;
|
|
#pragma warning restore 0436
|
|
var parameters = constr.getParameterTypes();
|
|
if ( parameters.Length == 2
|
|
&& parameters[0] == java.lang.Integer.TYPE
|
|
&& parameters[1].isMemberClass())
|
|
{
|
|
var created = constr.newInstance(new object[] {
|
|
java.lang.Integer.valueOf(sourceConstructFlags),
|
|
null
|
|
});
|
|
return new object[] { created };
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
namespace Microsoft.FSharp.Core
|
|
{
|
|
[java.attr.Discard] // discard in output
|
|
public class CompilationMappingAttribute { }
|
|
}
|