Added ikvmstub -parameters option to add parameter names to stub classes.

This commit is contained in:
jfrijters 2013-08-12 09:02:13 +00:00
Родитель 5befcded8a
Коммит 3c0a730167
5 изменённых файлов: 180 добавлений и 88 удалений

Просмотреть файл

@ -40,6 +40,7 @@ static class NetExp
private static bool includeSerialVersionUID;
private static bool includeNonPublicInterfaces;
private static bool includeNonPublicMembers;
private static bool includeParameterNames;
private static List<string> namespaces = new List<string>();
static int Main(string[] args)
@ -106,6 +107,10 @@ static class NetExp
{
forwarders = true;
}
else if(s == "-parameters")
{
includeParameterNames = true;
}
else
{
// unrecognized option, or multiple assemblies, print usage message and exit
@ -134,6 +139,7 @@ static class NetExp
Console.Error.WriteLine(" -lib:<dir> Additional directories to search for references");
Console.Error.WriteLine(" -namespace:<ns> Only include types from specified namespace");
Console.Error.WriteLine(" -forwarders Export forwarded types too");
Console.Error.WriteLine(" -parameters Emit Java 8 classes with parameter names");
return 1;
}
if(File.Exists(assemblyNameOrPath) && nostdlib)
@ -323,7 +329,7 @@ static class NetExp
{
zipCount++;
MemoryStream mem = new MemoryStream();
IKVM.StubGen.StubGenerator.WriteClass(mem, tw, includeNonPublicInterfaces, includeNonPublicMembers, includeSerialVersionUID);
IKVM.StubGen.StubGenerator.WriteClass(mem, tw, includeNonPublicInterfaces, includeNonPublicMembers, includeSerialVersionUID, includeParameterNames);
ZipEntry entry = new ZipEntry(tw.Name.Replace('.', '/') + ".class");
entry.Size = mem.Position;
zipFile.PutNextEntry(entry);
@ -387,6 +393,7 @@ static class NetExp
try
{
ProcessClass(c);
WriteClass(c);
}
catch (Exception x)
{
@ -400,7 +407,6 @@ static class NetExp
throw;
}
}
WriteClass(c);
}
}
} while(keepGoing);
@ -497,7 +503,7 @@ static class Intrinsics
static class StaticCompiler
{
internal static readonly Universe Universe = new Universe();
internal static readonly Universe Universe = new Universe(UniverseOptions.EnableFunctionPointers);
internal static readonly AssemblyResolver Resolver = new AssemblyResolver();
internal static Assembly runtimeAssembly;

Просмотреть файл

@ -49,7 +49,7 @@ namespace IKVM.NativeCode.gnu.java.net.protocol.ikvmres
MemoryStream mem = new MemoryStream();
#if !FIRST_PASS
bool includeNonPublicInterfaces = !"true".Equals(global::java.lang.Props.props.getProperty("ikvm.stubgen.skipNonPublicInterfaces"), StringComparison.OrdinalIgnoreCase);
IKVM.StubGen.StubGenerator.WriteClass(mem, TypeWrapper.FromClass(c), includeNonPublicInterfaces, false, false);
IKVM.StubGen.StubGenerator.WriteClass(mem, TypeWrapper.FromClass(c), includeNonPublicInterfaces, false, false, false);
#endif
return mem.ToArray();
}
@ -117,11 +117,7 @@ namespace IKVM.NativeCode.java.lang
public static string getBootClassPath()
{
#if FIRST_PASS
return null;
#else
return VirtualFileSystem.GetAssemblyClassesPath(JVM.CoreAssembly);
#endif
}
}
}
@ -146,60 +142,15 @@ namespace IKVM.NativeCode.ikvm.@internal
}
}
namespace stubgen
static class AnnotationAttributeBase
{
static class StubGenerator
public static object newAnnotationInvocationHandler(jlClass type, object memberValues)
{
public static int getRealModifiers(jlClass c)
{
return (int)TypeWrapper.FromClass(c).Modifiers;
}
public static string getAssemblyName(jlClass c)
{
TypeWrapper wrapper = TypeWrapper.FromClass(c);
ClassLoaderWrapper loader = wrapper.GetClassLoader();
IKVM.Internal.AssemblyClassLoader acl = loader as IKVM.Internal.AssemblyClassLoader;
if(acl != null)
{
return acl.GetAssembly(wrapper).FullName;
}
else
{
return ((GenericClassLoaderWrapper)loader).GetName();
}
}
public static object getFieldConstantValue(object field)
{
return FieldWrapper.FromField(field).GetConstant();
}
public static bool isFieldDeprecated(object field)
{
FieldWrapper fieldWrapper = FieldWrapper.FromField(field);
FieldInfo fi = fieldWrapper.GetField();
if(fi != null)
{
return fi.IsDefined(typeof(ObsoleteAttribute), false);
}
return false;
}
public static bool isMethodDeprecated(object method)
{
MethodWrapper mw = MethodWrapper.FromMethodOrConstructor(method);
MethodBase mb = mw.GetMethod();
return mb != null && mb.IsDefined(typeof(ObsoleteAttribute), false);
}
public static bool isClassDeprecated(jlClass clazz)
{
Type type = TypeWrapper.FromClass(clazz).TypeAsTBD;
// we need to check type for null, because ReflectionOnly
// generated delegate inner interfaces don't really exist
return type != null && type.IsDefined(typeof(ObsoleteAttribute), false);
}
#if FIRST_PASS
return null;
#else
return new global::sun.reflect.annotation.AnnotationInvocationHandler(type, (global::java.util.Map)memberValues);
#endif
}
}
}
@ -228,7 +179,9 @@ namespace IKVM.NativeCode.ikvm.runtime
TypeWrapper tw = wrapper.LoadClass(name);
if (tw == null)
{
throw new ClassNotFoundException(name);
Tracer.Info(Tracer.ClassLoading, "Failed to load class \"{0}\" from {1}", name, _this);
global::java.lang.Throwable.suppressFillInStackTrace = true;
throw new global::java.lang.ClassNotFoundException(name);
}
Tracer.Info(Tracer.ClassLoading, "Loaded class \"{0}\" from {1}", name, _this);
return tw.ClassObject;

Просмотреть файл

@ -830,6 +830,31 @@ namespace IKVM.StubGen
}
}
sealed class MethodParametersAttribute : ClassFileAttribute
{
private readonly ClassFileWriter classFile;
private readonly ushort[] names;
internal MethodParametersAttribute(ClassFileWriter classFile, ushort[] names)
: base(classFile.AddUtf8("MethodParameters"))
{
this.classFile = classFile;
this.names = names;
}
public override void Write(BigEndianStream bes)
{
base.Write(bes);
bes.WriteUInt32((uint)(1 + names.Length * 4));
bes.WriteByte((byte)names.Length);
foreach (ushort idx in names)
{
bes.WriteUInt16(idx);
bes.WriteUInt16(0);
}
}
}
interface IAttributeOwner
{
void AddAttribute(ClassFileAttribute attrib);

Просмотреть файл

@ -37,7 +37,7 @@ namespace IKVM.StubGen
{
static class StubGenerator
{
internal static void WriteClass(Stream stream, TypeWrapper tw, bool includeNonPublicInterfaces, bool includeNonPublicMembers, bool includeSerialVersionUID)
internal static void WriteClass(Stream stream, TypeWrapper tw, bool includeNonPublicInterfaces, bool includeNonPublicMembers, bool includeSerialVersionUID, bool includeParameterNames)
{
string name = tw.Name.Replace('.', '/');
string super = null;
@ -49,7 +49,7 @@ namespace IKVM.StubGen
{
super = tw.BaseTypeWrapper.Name.Replace('.', '/');
}
ClassFileWriter writer = new ClassFileWriter(tw.Modifiers, name, super, 0, 49);
ClassFileWriter writer = new ClassFileWriter(tw.Modifiers, name, super, 0, includeParameterNames ? (ushort)52 : (ushort)49);
foreach (TypeWrapper iface in tw.Interfaces)
{
if (iface.IsPublic || includeNonPublicInterfaces)
@ -185,6 +185,22 @@ namespace IKVM.StubGen
{
m.AddAttribute(new AnnotationDefaultClassFileAttribute(writer, GetAnnotationDefault(writer, attr.ConstructorArguments[0])));
}
if (includeParameterNames)
{
ParameterInfo[] parameters = mb.GetParameters();
if (parameters.Length != 0)
{
ushort[] names = new ushort[parameters.Length];
for (int i = 0; i < names.Length; i++)
{
if (parameters[i].Name != null)
{
names[i] = writer.AddUtf8(parameters[i].Name);
}
}
m.AddAttribute(new MethodParametersAttribute(writer, names));
}
}
}
string sig = tw.GetGenericMethodSignature(mw);
if (sig != null)
@ -252,7 +268,7 @@ namespace IKVM.StubGen
{
attr = new RuntimeVisibleAnnotationsAttribute(writer);
}
attr.Add(UnpackArray((IList<CustomAttributeTypedArgument>)cad.ConstructorArguments[0].Value));
attr.Add(ann);
}
}
if (attr != null)
@ -290,7 +306,7 @@ namespace IKVM.StubGen
}
param = new RuntimeVisibleAnnotationsAttribute(writer);
}
param.Add(UnpackArray((IList<CustomAttributeTypedArgument>)cad.ConstructorArguments[0].Value));
param.Add(ann);
}
}
if (attr != null)
@ -310,13 +326,84 @@ namespace IKVM.StubGen
private static object[] GetAnnotation(CustomAttributeData cad)
{
if (cad.ConstructorArguments.Count == 1 && cad.ConstructorArguments[0].ArgumentType == typeof(object[]) &&
(cad.Constructor.DeclaringType.IsSubclassOf(JVM.Import(typeof(ikvm.@internal.AnnotationAttributeBase)))
|| cad.Constructor.DeclaringType == JVM.Import(typeof(DynamicAnnotationAttribute))))
(cad.Constructor.DeclaringType.BaseType == typeof(ikvm.@internal.AnnotationAttributeBase)
|| cad.Constructor.DeclaringType == typeof(DynamicAnnotationAttribute)))
{
return UnpackArray((IList<CustomAttributeTypedArgument>)cad.ConstructorArguments[0].Value);
}
else if (cad.Constructor.DeclaringType.BaseType == typeof(ikvm.@internal.AnnotationAttributeBase))
{
string annotationType = GetAnnotationInterface(cad);
if (annotationType != null)
{
// this is a custom attribute annotation applied in a non-Java module
List<object> list = new List<object>();
list.Add(AnnotationDefaultAttribute.TAG_ANNOTATION);
list.Add("L" + annotationType.Replace('.', '/') + ";");
ParameterInfo[] parameters = cad.Constructor.GetParameters();
for (int i = 0; i < parameters.Length; i++)
{
list.Add(parameters[i].Name);
list.Add(EncodeAnnotationValue(cad.ConstructorArguments[i]));
}
foreach (CustomAttributeNamedArgument arg in cad.NamedArguments)
{
list.Add(arg.MemberInfo.Name);
list.Add(EncodeAnnotationValue(arg.TypedValue));
}
return list.ToArray();
}
}
return null;
}
private static string GetAnnotationInterface(CustomAttributeData cad)
{
object[] attr = cad.Constructor.DeclaringType.GetCustomAttributes(typeof(IKVM.Attributes.ImplementsAttribute), false);
if (attr.Length == 1)
{
string[] interfaces = ((IKVM.Attributes.ImplementsAttribute)attr[0]).Interfaces;
if (interfaces.Length == 1)
{
return interfaces[0];
}
}
return null;
}
private static object EncodeAnnotationValue(CustomAttributeTypedArgument arg)
{
if (arg.ArgumentType.IsEnum)
{
// if GetWrapperFromType returns null, we've got an ikvmc synthesized .NET enum nested inside a Java enum
TypeWrapper tw = ClassLoaderWrapper.GetWrapperFromType(arg.ArgumentType) ?? ClassLoaderWrapper.GetWrapperFromType(arg.ArgumentType.DeclaringType);
return new object[] { AnnotationDefaultAttribute.TAG_ENUM, EncodeTypeName(tw), Enum.GetName(arg.ArgumentType, arg.Value) };
}
else if (arg.Value is Type)
{
return new object[] { AnnotationDefaultAttribute.TAG_CLASS, EncodeTypeName(ClassLoaderWrapper.GetWrapperFromType((Type)arg.Value)) };
}
else if (arg.ArgumentType.IsArray)
{
IList<CustomAttributeTypedArgument> array = (IList<CustomAttributeTypedArgument>)arg.Value;
object[] arr = new object[array.Count + 1];
arr[0] = AnnotationDefaultAttribute.TAG_ARRAY;
for (int i = 0; i < array.Count; i++)
{
arr[i + 1] = EncodeAnnotationValue(array[i]);
}
return arr;
}
else
{
return arg.Value;
}
}
private static string EncodeTypeName(TypeWrapper tw)
{
return tw.SigName.Replace('.', '/');
}
#endif
private static object[] UnpackArray(IList<CustomAttributeTypedArgument> list)
@ -438,10 +525,31 @@ namespace IKVM.StubGen
"value",
targets.ToArray()
});
if (Experimental.JDK_8 && IsRepeatableAnnotation(tw))
{
annot.Add(new object[] {
AnnotationDefaultAttribute.TAG_ANNOTATION,
"Ljava/lang/annotation/Repeatable;",
"value",
new object[] { AnnotationDefaultAttribute.TAG_CLASS, "L" + (tw.Name + DotNetTypeWrapper.AttributeAnnotationMultipleSuffix).Replace('.', '/') + ";" }
});
}
writer.AddAttribute(annot);
}
}
private static bool IsRepeatableAnnotation(TypeWrapper tw)
{
foreach (TypeWrapper nested in tw.InnerClasses)
{
if (nested.Name == tw.Name + DotNetTypeWrapper.AttributeAnnotationMultipleSuffix)
{
return true;
}
}
return false;
}
private static byte[] GetAnnotationDefault(ClassFileWriter classFile, TypeWrapper type)
{
MemoryStream mem = new MemoryStream();

Просмотреть файл

@ -39,6 +39,25 @@ namespace IKVM.Internal
|| String.CompareOrdinal(path, 0, RootPath, 0, RootPath.Length) == 0;
}
internal static string GetAssemblyClassesPath(Assembly asm)
{
#if FIRST_PASS
return null;
#else
// we can't use java.io.File.separatorChar here, because we're invoked by the system property setup code
return RootPath + "assembly" + System.IO.Path.DirectorySeparatorChar + VfsAssembliesDirectory.GetName(asm) + System.IO.Path.DirectorySeparatorChar + "classes" + System.IO.Path.DirectorySeparatorChar;
#endif
}
internal static string GetAssemblyResourcesPath(Assembly asm)
{
#if FIRST_PASS
return null;
#else
return RootPath + "assembly" + System.IO.Path.DirectorySeparatorChar + VfsAssembliesDirectory.GetName(asm) + System.IO.Path.DirectorySeparatorChar + "resources" + System.IO.Path.DirectorySeparatorChar;
#endif
}
#if !FIRST_PASS
private static VfsDirectory root;
@ -110,25 +129,6 @@ namespace IKVM.Internal
}
}
internal static string GetAssemblyClassesPath(Assembly asm)
{
#if FIRST_PASS
return null;
#else
// we can't use java.io.File.separatorChar here, because we're invoked by the system property setup code
return RootPath + "assembly" + System.IO.Path.DirectorySeparatorChar + VfsAssembliesDirectory.GetName(asm) + System.IO.Path.DirectorySeparatorChar + "classes" + System.IO.Path.DirectorySeparatorChar;
#endif
}
internal static string GetAssemblyResourcesPath(Assembly asm)
{
#if FIRST_PASS
return null;
#else
return RootPath + "assembly" + System.IO.Path.DirectorySeparatorChar + VfsAssembliesDirectory.GetName(asm) + System.IO.Path.DirectorySeparatorChar + "resources" + System.IO.Path.DirectorySeparatorChar;
#endif
}
private sealed class VfsAssembliesDirectory : VfsDirectory
{
internal override VfsEntry GetEntry(string name)
@ -577,7 +577,7 @@ namespace IKVM.Internal
{
System.IO.MemoryStream mem = new System.IO.MemoryStream();
bool includeNonPublicInterfaces = !"true".Equals(java.lang.Props.props.getProperty("ikvm.stubgen.skipNonPublicInterfaces"), StringComparison.OrdinalIgnoreCase);
IKVM.StubGen.StubGenerator.WriteClass(mem, tw, includeNonPublicInterfaces, false, false);
IKVM.StubGen.StubGenerator.WriteClass(mem, tw, includeNonPublicInterfaces, false, false, false);
buf = mem.ToArray();
}
#endif
@ -985,7 +985,7 @@ namespace IKVM.Internal
#if FIRST_PASS
return false;
#else
return access == IKVM.NativeCode.java.io.Win32FileSystem.ACCESS_READ && GetVfsEntry(path) != null;
return access == Java_java_io_Win32FileSystem.ACCESS_READ && GetVfsEntry(path) != null;
#endif
}