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-07 10:16:48 +0400
committerjfrijters <jfrijters>2013-08-07 10:16:48 +0400
commit71193b82e8a3029e2acc8413ac032b17bfdae1d0 (patch)
treef858686a3c9f8ebaa888353bd45feae2b1abaf44
parentbf04f25dc09a5811abc7a7670c8c3503ea6982ba (diff)
Compile anonymous and local classes as nested types.
-rw-r--r--runtime/DynamicTypeWrapper.cs39
-rw-r--r--runtime/TypeWrapper.cs27
2 files changed, 53 insertions, 13 deletions
diff --git a/runtime/DynamicTypeWrapper.cs b/runtime/DynamicTypeWrapper.cs
index 57825982..f1692b3b 100644
--- a/runtime/DynamicTypeWrapper.cs
+++ b/runtime/DynamicTypeWrapper.cs
@@ -610,16 +610,24 @@ namespace IKVM.Internal
bool cantNest = false;
bool setModifiers = false;
TypeBuilder enclosing = null;
+ string enclosingClassName = null;
// we only compile inner classes as nested types in the static compiler, because it has a higher cost
// and doesn't buy us anything in dynamic mode (and if fact, due to an FXBUG it would make handling
// the TypeResolve event very hard)
ClassFile.InnerClass outerClass = getOuterClass();
if (outerClass.outerClass != 0)
{
- string enclosingClassName = classFile.GetConstantPoolClass(outerClass.outerClass);
+ enclosingClassName = classFile.GetConstantPoolClass(outerClass.outerClass);
+ }
+ else if (f.EnclosingMethod != null)
+ {
+ enclosingClassName = f.EnclosingMethod[0];
+ }
+ if (enclosingClassName != null)
+ {
if (!CheckInnerOuterNames(f.Name, enclosingClassName))
{
- Tracer.Warning(Tracer.Compiler, "Incorrect InnerClasses attribute on {0}", f.Name);
+ Tracer.Warning(Tracer.Compiler, "Incorrect {0} attribute on {1}", outerClass.outerClass != 0 ? "InnerClasses" : "EnclosingMethod", f.Name);
}
else
{
@@ -636,7 +644,7 @@ namespace IKVM.Internal
// make sure the relationship is reciprocal (otherwise we run the risk of
// baking the outer type before the inner type) and that the inner and outer
// class live in the same class loader (when doing a multi target compilation,
- // it is possible to split the two classes acros assemblies)
+ // it is possible to split the two classes across assemblies)
JavaTypeImpl oimpl = enclosingClassWrapper.impl as JavaTypeImpl;
if (oimpl != null && enclosingClassWrapper.GetClassLoader() == wrapper.GetClassLoader())
{
@@ -651,8 +659,8 @@ namespace IKVM.Internal
bool ok = false;
for (int i = 0; i < outerInnerClasses.Length; i++)
{
- if (outerInnerClasses[i].outerClass != 0
- && outerClassFile.GetConstantPoolClass(outerInnerClasses[i].outerClass) == outerClassFile.Name
+ if (((outerInnerClasses[i].outerClass != 0 && outerClassFile.GetConstantPoolClass(outerInnerClasses[i].outerClass) == outerClassFile.Name)
+ || (outerInnerClasses[i].outerClass == 0 && outerClass.outerClass == 0))
&& outerInnerClasses[i].innerClass != 0
&& outerClassFile.GetConstantPoolClass(outerInnerClasses[i].innerClass) == f.Name)
{
@@ -674,6 +682,11 @@ namespace IKVM.Internal
{
enclosingClassWrapper.CreateStep2();
enclosing = oimpl.typeBuilder;
+ if (outerClass.outerClass == 0)
+ {
+ // we need to record that we're not an inner classes, but an enclosed class
+ typeAttribs |= TypeAttributes.SpecialName;
+ }
}
else
{
@@ -772,14 +785,16 @@ namespace IKVM.Internal
// When we're statically compiling, we associate the typeBuilder with the wrapper. This enables types in referenced assemblies to refer back to
// types that we're currently compiling (i.e. a cyclic dependency between the currently assembly we're compiling and a referenced assembly).
wrapper.GetClassLoader().SetWrapperForType(typeBuilder, wrapper);
- if (enclosing != null && cantNest)
- {
- AttributeHelper.SetNonNestedOuterClass(typeBuilder, enclosingClassWrapper.Name);
- AttributeHelper.SetNonNestedInnerClass(enclosing, f.Name);
- }
- if (outerClass.outerClass != 0 && enclosing == null)
+ if (outerClass.outerClass != 0)
{
- AttributeHelper.SetNonNestedOuterClass(typeBuilder, classFile.GetConstantPoolClass(outerClass.outerClass));
+ if (enclosing != null && cantNest)
+ {
+ AttributeHelper.SetNonNestedInnerClass(enclosing, f.Name);
+ }
+ if (enclosing == null || cantNest)
+ {
+ AttributeHelper.SetNonNestedOuterClass(typeBuilder, enclosingClassName);
+ }
}
if (classFile.InnerClasses != null)
{
diff --git a/runtime/TypeWrapper.cs b/runtime/TypeWrapper.cs
index e0aa3768..68c4cc74 100644
--- a/runtime/TypeWrapper.cs
+++ b/runtime/TypeWrapper.cs
@@ -1107,6 +1107,11 @@ namespace IKVM.Internal
return type.IsDefined(typeofNoPackagePrefixAttribute, false) || type.Assembly.IsDefined(typeofNoPackagePrefixAttribute, false);
}
+ internal static bool HasEnclosingMethodAttribute(Type type)
+ {
+ return type.IsDefined(typeofEnclosingMethodAttribute, false);
+ }
+
internal static EnclosingMethodAttribute GetEnclosingMethodAttribute(Type type)
{
#if !STATIC_COMPILER && !STUB_GENERATOR
@@ -3878,6 +3883,18 @@ namespace IKVM.Internal
return interfaceWrappers;
}
+ private static bool IsNestedTypeAnonymousOrLocalClass(Type type)
+ {
+ switch (type.Attributes & (TypeAttributes.SpecialName | TypeAttributes.VisibilityMask))
+ {
+ case TypeAttributes.SpecialName | TypeAttributes.NestedPublic:
+ case TypeAttributes.SpecialName | TypeAttributes.NestedAssembly:
+ return AttributeHelper.HasEnclosingMethodAttribute(type);
+ default:
+ return false;
+ }
+ }
+
internal override TypeWrapper[] InnerClasses
{
get
@@ -3894,7 +3911,7 @@ namespace IKVM.Internal
// (we can't put a HideFromJavaAttribute on it, because we do want the class to be visible as a $Proxy)
continue;
}
- if(!AttributeHelper.IsHideFromJava(nestedTypes[i]))
+ if(!IsNestedTypeAnonymousOrLocalClass(nestedTypes[i]) && !AttributeHelper.IsHideFromJava(nestedTypes[i]))
{
wrappers.Add(ClassLoaderWrapper.GetWrapperFromType(nestedTypes[i]));
}
@@ -3911,6 +3928,10 @@ namespace IKVM.Internal
{
get
{
+ if(IsNestedTypeAnonymousOrLocalClass(type))
+ {
+ return null;
+ }
Type declaringType = type.DeclaringType;
if(declaringType != null)
{
@@ -4848,6 +4869,10 @@ namespace IKVM.Internal
{
return DeclaringTypeWrapper.GetSourceFileName();
}
+ if(IsNestedTypeAnonymousOrLocalClass(type))
+ {
+ return ClassLoaderWrapper.GetWrapperFromType(type.DeclaringType).GetSourceFileName();
+ }
if(type.Module.IsDefined(typeof(SourceFileAttribute), false))
{
return type.Name + ".java";