Bug 468116: [otdre] weaving access to indirectly inherited base method
fails in OT/Equinox settings
- test (was already passing)
- change data in OTSpecialAccessAttribute to register more base classes
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTSpecialAccessAttribute.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTSpecialAccessAttribute.java
index 1892da1..4e2433f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTSpecialAccessAttribute.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/OTSpecialAccessAttribute.java
@@ -31,6 +31,7 @@
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.parser.TerminalTokens;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
@@ -117,7 +118,16 @@
this.method.declaringClass.attributeName(),
this.method.selector
}, sep);
- writeName(this.boundBaseclass.attributeName()); // where to weave into
+ char[] weaveIntoClasses = this.boundBaseclass.attributeName();
+ if (OTSpecialAccessAttribute.this._weavingScheme == WeavingScheme.OTDRE) {
+ // for OTDRE pass all classes to weave from boundBaseclass up to the actual declaring class (:-separated)
+ ReferenceBinding someClass = this.boundBaseclass.getRealClass();
+ if (someClass != null && TypeBinding.notEquals(someClass, this.method.declaringClass)) {
+ while ((someClass = someClass.superclass()) != null && TypeBinding.notEquals(someClass, this.method.declaringClass))
+ weaveIntoClasses = CharOperation.concat(weaveIntoClasses, someClass.attributeName(), ':');
+ }
+ }
+ writeName(weaveIntoClasses);
writeName(encodedName);
writeName(this.method.signature());
}
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmClassVisitor.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmClassVisitor.java
index 46c01bc..c235796 100644
--- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmClassVisitor.java
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/AsmClassVisitor.java
@@ -25,6 +25,7 @@
import org.eclipse.objectteams.otredyn.bytecode.asm.Attributes.CallinBindingsAttribute.MultiBinding;
import org.eclipse.objectteams.otredyn.bytecode.asm.Attributes.CallinPrecedenceAttribute;
import org.eclipse.objectteams.otredyn.bytecode.asm.Attributes.OTSpecialAccessAttribute;
+import org.eclipse.objectteams.otredyn.bytecode.asm.Attributes.OTSpecialAccessAttribute.DecapsMethod;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
@@ -110,11 +111,12 @@
int[] baseFlags = multiBindings[i].getBaseFlags();
boolean handleCovariantReturn = multiBindings[i].isHandleCovariantReturn();
for (int j = 0; j < baseMethodNames.length; j++) {
+ String declaringBaseClassName = declaringBaseClassNames[j];
Binding binding = new Binding(clazz, roleClassName, callinLabel, baseClassName,
- baseMethodNames[j], baseMethodSignatures[j], declaringBaseClassNames[j],
+ baseMethodNames[j], baseMethodSignatures[j], declaringBaseClassName,
callinModifier, callinIds[j], baseFlags[j], handleCovariantReturn);
clazz.addBinding(binding);
- clazz.boundBaseClasses.add(declaringBaseClassNames[j].replace('/', '.'));
+ clazz.boundBaseClasses.add(declaringBaseClassName.replace('/', '.'));
}
}
} else if (attribute.type.equals(Attributes.ATTRIBUTE_CALLIN_PRECEDENCE)) {
@@ -123,7 +125,12 @@
} else if (attribute.type.equals(Attributes.ATTRIBUTE_OT_CLASS_FLAGS)) {
clazz.setOTClassFlags(((OTClassFlagsAttribute)attribute).flags);
} else if (attribute.type.equals(Attributes.ATTRIBUTE_OT_SPECIAL_ACCESS)) {
- ((OTSpecialAccessAttribute)attribute).registerAt(clazz);
+ OTSpecialAccessAttribute accessAttribute = (OTSpecialAccessAttribute)attribute;
+ accessAttribute.registerAt(clazz);
+ for (DecapsMethod method : accessAttribute.methods) {
+ for (String weaveInto : method.weaveIntoClasses)
+ clazz.boundBaseClasses.add(weaveInto);
+ }
} else if (attribute.type.equals(Attributes.ATTRIBUTE_ROLE_BASE_BINDINGS)) {
for (String base : ((RoleBaseBindingsAttribute) attribute).bases) {
clazz.boundBaseClasses.add(base.replace('/', '.'));
diff --git a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java
index 031df64..571eed6 100644
--- a/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java
+++ b/plugins/org.eclipse.objectteams.otredyn/src/org/eclipse/objectteams/otredyn/bytecode/asm/Attributes.java
@@ -286,11 +286,13 @@
}
}
class DecapsMethod {
- String baseclass, name, desc;
+ String[] weaveIntoClasses;
+ String declaringClass, name, desc;
int perTeamAccessId;
boolean isStatic;
- DecapsMethod(String baseclass, String name, String desc, int id, boolean isStatic) {
- this.baseclass = baseclass;
+ DecapsMethod(String weaveIntoClasses, String declaringClass, String name, String desc, int id, boolean isStatic) {
+ this.weaveIntoClasses = weaveIntoClasses.split(":");
+ this.declaringClass = declaringClass;
this.name = name;
this.desc = desc;
this.perTeamAccessId = id;
@@ -346,11 +348,11 @@
String methodDesc = cr.readUTF8(off+4, buf);
int accessId = cr.readUnsignedShort(off+6);
boolean isStatic = false;
- String baseClass;
+ String declaringClass;
String methodName;
if (encodedName.charAt(0) == '<') {
// constructor
- baseClass = className;
+ declaringClass = className;
methodName = encodedName;
isStatic = true; // use static accessor
} else {
@@ -359,10 +361,10 @@
pos = encodedName.indexOf('!');
isStatic = true;
}
- baseClass = encodedName.substring(0, pos);
+ declaringClass = encodedName.substring(0, pos);
methodName = encodedName.substring(pos+1);
}
- this.methods.add(new DecapsMethod(baseClass, methodName, methodDesc, accessId, isStatic));
+ this.methods.add(new DecapsMethod(className, declaringClass, methodName, methodDesc, accessId, isStatic));
}
private void readFieldAccess(ClassReader cr, int off, char[] buf) {
int accessId = cr.readUnsignedShort(off);
@@ -382,11 +384,11 @@
// FIXME(SH): the following may need adaptation for OT/Equinox or other multi-classloader settings:
// bypassing the identifier provider (we don't have a Class<?> yet):
// String boundClassIdentifier = provider.getBoundClassIdentifier(clazz, dMethod.baseclass);
- AbstractBoundClass baseclass = repo.getBoundClass(dMethod.baseclass, dMethod.baseclass.replace('.', '/'), clazz.getClassLoader());
+ AbstractBoundClass baseclass = repo.getBoundClass(dMethod.declaringClass, dMethod.declaringClass.replace('.', '/'), clazz.getClassLoader());
// register the target method:
baseclass.getMethod(dMethod.name, dMethod.desc, false/*covariantReturn*/, dMethod.isStatic);
clazz.recordAccessId(dMethod.perTeamAccessId);
- clazz.addBinding(new Binding(clazz, dMethod.baseclass, dMethod.name, dMethod.desc, dMethod.perTeamAccessId, IBinding.BindingType.METHOD_ACCESS));
+ clazz.addBinding(new Binding(clazz, dMethod.declaringClass, dMethod.name, dMethod.desc, dMethod.perTeamAccessId, IBinding.BindingType.METHOD_ACCESS));
}
for (DecapsField dField: this.fields) {
diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/calloutbinding/OverridingAccessRestrictions.java b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/calloutbinding/OverridingAccessRestrictions.java
index fa04665..1c0bcc2 100644
--- a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/calloutbinding/OverridingAccessRestrictions.java
+++ b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/calloutbinding/OverridingAccessRestrictions.java
@@ -1613,4 +1613,36 @@
"C1::printStr1(): C1.str\n" +
"T1.R1::getStr1(): C1.str");
}
+ public void testX() throws Exception {
+ runConformTest(
+ new String[] {
+ "pt/MyTeam.java",
+ "package pt;\n" +
+ "public team class MyTeam {\n" +
+ " protected class R playedBy p3.C3 {\n" +
+ " protected void rm() -> void mc();\n" +
+ " }\n" +
+ " void test(p3.C3 as R r) {\n" +
+ " r.rm();\n" +
+ " }\n" +
+ " public static void main(String... args) {\n" +
+ " new MyTeam().test(new p3.C3());\n" +
+ " }\n" +
+ "}\n",
+ "p1/C1.java",
+ "package p1;\n" +
+ "public class C1 {\n" +
+ " protected void mc() {\n" +
+ " System.out.print(13);\n" +
+ " }\n" +
+ "}\n",
+ "p2/C2.java",
+ "package p2;\n" +
+ "public class C2 extends p1.C1 {}\n",
+ "p3/C3.java",
+ "package p3;\n" +
+ "public class C3 extends p2.C2 {}\n",
+ },
+ "13");
+ }
}