Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfrijters <jfrijters>2013-08-12 13:02:13 +0400
committerjfrijters <jfrijters>2013-08-12 13:02:13 +0400
commit3c0a730167f0cfb88777d477bd2960bd78fcfe31 (patch)
tree07508da19295aeeafb3e1448da18cca33e5a014d
parent5befcded8aa819499e9033140f628c306d436e5f (diff)
Added ikvmstub -parameters option to add parameter names to stub classes.
-rw-r--r--ikvmstub/ikvmstub.cs12
-rw-r--r--runtime/common.cs69
-rw-r--r--runtime/stubgen/ClassFileWriter.cs25
-rw-r--r--runtime/stubgen/StubGenerator.cs120
-rw-r--r--runtime/vfs.cs42
5 files changed, 180 insertions, 88 deletions
diff --git a/ikvmstub/ikvmstub.cs b/ikvmstub/ikvmstub.cs
index 71446c9d..5f882cae 100644
--- a/ikvmstub/ikvmstub.cs
+++ b/ikvmstub/ikvmstub.cs
@@ -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;
diff --git a/runtime/common.cs b/runtime/common.cs
index 75f39be6..eff75684 100644
--- a/runtime/common.cs
+++ b/runtime/common.cs
@@ -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;
diff --git a/runtime/stubgen/ClassFileWriter.cs b/runtime/stubgen/ClassFileWriter.cs
index 327591c9..ded62674 100644
--- a/runtime/stubgen/ClassFileWriter.cs
+++ b/runtime/stubgen/ClassFileWriter.cs
@@ -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);
diff --git a/runtime/stubgen/StubGenerator.cs b/runtime/stubgen/StubGenerator.cs
index 206cd182..1aa6f937 100644
--- a/runtime/stubgen/StubGenerator.cs
+++ b/runtime/stubgen/StubGenerator.cs
@@ -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();
diff --git a/runtime/vfs.cs b/runtime/vfs.cs
index 8db1165e..3ff13c3e 100644
--- a/runtime/vfs.cs
+++ b/runtime/vfs.cs
@@ -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
}