Bug 460525 - Evaluating PlayedBy attribute may cause bad processing
order
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index f58cb49..6da45e7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -64,6 +64,7 @@
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
+import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.AbstractAttribute;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
@@ -807,8 +808,8 @@
this.fields[i].setAnnotations(createAnnotations(binaryField.getAnnotations(), this.environment, missingTypeNames));
}
}
- }
- }
+ }
+ }
}
//{ObjectTeams: some fields are indeed value parameters:
private SyntheticArgumentBinding[] valueParameters = NO_SYNTH_ARGUMENTS;
@@ -2220,8 +2221,18 @@
}
//{ObjectTeams:
public ReferenceBinding baseclass () {
- if (this.baseclass == null)
+ if (this.baseclass == null) {
+ if (this.roleModel != null) {
+ // check if evaluation of a PlayedBy attribute had to be deferred:
+ AbstractAttribute attribute = this.roleModel.getAttribute(IOTConstants.PLAYEDBY_NAME);
+ if (attribute != null) {
+ attribute.evaluate(this, this.environment, null);
+ this.roleModel.removeAttribute(attribute);
+ return baseclass();
+ }
+ }
return null;
+ }
if (this.baseclass instanceof UnresolvedReferenceBinding)
this.baseclass = ((UnresolvedReferenceBinding) this.baseclass).resolve(this.environment, false);
return this.baseclass;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/SingleValueAttribute.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/SingleValueAttribute.java
index 8b08afa..500b18d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/SingleValueAttribute.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/bytecode/SingleValueAttribute.java
@@ -1,7 +1,7 @@
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
- * Copyright 2004, 2006 Fraunhofer Gesellschaft, Munich, Germany,
+ * Copyright 2004, 2015 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute for Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
* Germany.
@@ -10,7 +10,6 @@
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
- * $Id: SingleValueAttribute.java 23416 2010-02-03 19:59:31Z stephan $
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
@@ -23,6 +22,7 @@
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileStruct;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
@@ -66,7 +66,6 @@
*
* </ul>
* @author stephan
- * @version $Id: SingleValueAttribute.java 23416 2010-02-03 19:59:31Z stephan $
*/
public class SingleValueAttribute
extends AbstractAttribute
@@ -200,6 +199,11 @@
ReferenceBinding currentType = staticPart;
ITeamAnchor anchor = null; // accumulate anchor path here
while (i<anchorPath.length) {
+ if (currentType instanceof BinaryTypeBinding && ((BinaryTypeBinding) currentType).version == 0) {
+ // necessary type on the path is not fully initialized (version is about the last field to be assigned in cachePartsFrom()).
+ roleType.roleModel.addAttribute(this);
+ return; // defer evaluation
+ }
FieldBinding f = currentType.getField(anchorPath[i], true);
if (f == null || !(f.type instanceof ReferenceBinding))
return; // not a valid anchor path.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/ModelElement.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/ModelElement.java
index c55a855..fd6a9b6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/ModelElement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/model/ModelElement.java
@@ -1,7 +1,7 @@
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
- * Copyright 2004, 2010 Fraunhofer Gesellschaft, Munich, Germany,
+ * Copyright 2004, 2015 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute for Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
* Germany.
@@ -36,14 +36,10 @@
/** Add an OT-specific bytecode attribute. */
- public void addAttribute (AbstractAttribute attr)
- {
- if (this._attributes == null)
- {
+ public void addAttribute (AbstractAttribute attr) {
+ if (this._attributes == null) {
this._attributes = new AbstractAttribute[]{attr};
- }
- else
- {
+ } else {
int len = this._attributes.length;
AbstractAttribute[] newAttrs = new AbstractAttribute[len+1];
System.arraycopy(this._attributes, 0, newAttrs, 0, len);
@@ -93,6 +89,22 @@
}
return null;
}
+
+ public void removeAttribute(AbstractAttribute attr) {
+ if (this._attributes == null) return;
+ int newLength = this._attributes.length-1;
+ AbstractAttribute[] newAttributes = new AbstractAttribute[newLength];
+ int i = 0;
+ for (AbstractAttribute anAttr : this._attributes) {
+ if (anAttr != attr) {
+ if (i == newLength)
+ return; // trying to insert the last item means: not found, so just don't change
+ newAttributes[i++] = anAttr;
+ }
+ }
+ this._attributes = newAttributes;
+ }
+
/**
* Write all OT-specific attributes of a given type binding to the given class file
* @param type the element whose attributes should be written
diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/rolesandteams/FileStructure.java b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/rolesandteams/FileStructure.java
index 40905e5..4755c2c 100644
--- a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/rolesandteams/FileStructure.java
+++ b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/rolesandteams/FileStructure.java
@@ -1,13 +1,12 @@
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
- * Copyright 2004, 2010 IT Service Omikron GmbH and others.
+ * Copyright 2004, 2015 IT Service Omikron GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
- * $Id$
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
@@ -2232,4 +2231,42 @@
customOptions,
null/*no custom requestor*/);
}
+
+ // Bug 460525 - Evaluating PlayedBy attribute may cause bad processing order
+ public void testBug460525() {
+ compileOrder = new String[][] {
+ new String[] {"pb/BaseTeam.java", "pt/TopTeam.java", "pt/TopTeam/Mid/InnerRole.java"},
+ new String[] {"pt/Main.java"}
+ };
+ runConformTest(
+ new String[] {
+ "pb/BaseTeam.java",
+ "package pb;\n" +
+ "public team class BaseTeam {\n" +
+ " public class BaseRole {}\n" +
+ "}\n",
+ "pt/TopTeam.java",
+ "package pt;\n" +
+ "import base pb.BaseTeam;\n" +
+ "public team class TopTeam {\n" +
+ " public team class Mid playedBy BaseTeam {\n" +
+ " public void mTest(BaseRole<@base> r) {}\n" +
+ " }\n" +
+ "}\n",
+ "pt/TopTeam/Mid/InnerRole.java",
+ "team package pt.TopTeam.Mid;\n" +
+ "public class InnerRole playedBy BaseRole<@Mid.base> {}\n",
+
+ // Compiling this class triggered:
+ // TopTeam.createFields() -> InnerRole.cachePartsFrom() -> InnerRole.evaluateOTAttributes() -> TopTeam.getField() -> NPE
+ "pt/Main.java",
+ "package pt;\n" +
+ "public class Main {\n" +
+ " final TopTeam t = new TopTeam();\n" +
+ " void test(final Mid<@t> m, InnerRole<@m> i) {\n" +
+ " m.mTest(i);\n" + // need this call to force resolving of InnerRole.baseclass()
+ " }\n" +
+ "}\n"
+ });
+ }
}