Bug 494254 - Validation for superBase declarations in aspectBindings

- includes a workaround for lacking session support in ASTParser
  (see the change & FIXME in SourceTypeBinding)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 6d389a9..40b8836 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -2491,6 +2491,9 @@
 	return resolveTypesFor(method, false);
 }
 public MethodBinding resolveTypesFor(MethodBinding method, boolean fromSynthetic) {
+	// FIXME(SH): scope is null for types returned from ASTParser.createBindings() -- shouldn't JDT support this?
+	if (this.scope == null)
+		return resolveTypesWithSuspendedTempErrorHandlingPolicy(method, fromSynthetic);
 //orig:
 	ProblemReporter problemReporter = this.scope.problemReporter();
 	IErrorHandlingPolicy suspendedPolicy = problemReporter.suspendTempErrorHandlingPolicy();
diff --git a/plugins/org.eclipse.objectteams.otdt.pde.ui/src/org/eclipse/objectteams/otdt/internal/pde/ui/OTPDEUIMessages.java b/plugins/org.eclipse.objectteams.otdt.pde.ui/src/org/eclipse/objectteams/otdt/internal/pde/ui/OTPDEUIMessages.java
index 58461b0..9bfaf6f 100644
--- a/plugins/org.eclipse.objectteams.otdt.pde.ui/src/org/eclipse/objectteams/otdt/internal/pde/ui/OTPDEUIMessages.java
+++ b/plugins/org.eclipse.objectteams.otdt.pde.ui/src/org/eclipse/objectteams/otdt/internal/pde/ui/OTPDEUIMessages.java
@@ -47,6 +47,9 @@
 	public static String Validation_NotAPackage_error;
 	public static String Validation_MissingPackage_error;
 	public static String Validation_MissingBindingForBasePackage_error;
+	public static String Validation_MissingSuperBasePackageDecl_error;
+	public static String Validation_PackageNotInSuperBase_error;
+	public static String Validation_UnnecessarySuperBase_warning;
 
 	public static String Validation_MissingAspectPackageExport_error;
 	public static String Resolution_AddAspectPackageExport_label;
diff --git a/plugins/org.eclipse.objectteams.otdt.pde.ui/src/org/eclipse/objectteams/otdt/internal/pde/ui/OTPDEUIMessages.properties b/plugins/org.eclipse.objectteams.otdt.pde.ui/src/org/eclipse/objectteams/otdt/internal/pde/ui/OTPDEUIMessages.properties
index f02e9e6..307c28e 100644
--- a/plugins/org.eclipse.objectteams.otdt.pde.ui/src/org/eclipse/objectteams/otdt/internal/pde/ui/OTPDEUIMessages.properties
+++ b/plugins/org.eclipse.objectteams.otdt.pde.ui/src/org/eclipse/objectteams/otdt/internal/pde/ui/OTPDEUIMessages.properties
@@ -15,6 +15,9 @@
 Validation_NotAPackage_error="{0} is an enclosing class, please use ''$'' as the separator for inner class names"
 Validation_MissingPackage_error=Missing package; cannot bind a team class in the default package
 Validation_MissingBindingForBasePackage_error=Team ''{0}'' lacks a binding for base package ''{1}''
+Validation_MissingSuperBasePackageDecl_error=Team ''{0}'' lacks a superBase declaration for base class ''{1}''
+Validation_PackageNotInSuperBase_error=Plug-in ''{0}'' does not provide package ''{1}''
+Validation_UnnecessarySuperBase_warning=Unnecessary superBase declaration ''{0}''
 
 Validation_MissingAspectPackageExport_error=Package {0} containing one or more bound teams must be exported.
 Resolution_AddAspectPackageExport_label=Export aspect package {0}
diff --git a/plugins/org.eclipse.objectteams.otdt.pde.ui/src/org/eclipse/objectteams/otdt/internal/pde/validation/BundleValidation.java b/plugins/org.eclipse.objectteams.otdt.pde.ui/src/org/eclipse/objectteams/otdt/internal/pde/validation/BundleValidation.java
index 90f691b..8ee7fb2 100644
--- a/plugins/org.eclipse.objectteams.otdt.pde.ui/src/org/eclipse/objectteams/otdt/internal/pde/validation/BundleValidation.java
+++ b/plugins/org.eclipse.objectteams.otdt.pde.ui/src/org/eclipse/objectteams/otdt/internal/pde/validation/BundleValidation.java
@@ -1,7 +1,7 @@
 /**********************************************************************
  * This file is part of "Object Teams Development Tooling"-Software
  * 
- * Copyright 2009, 2014 Technical University Berlin, Germany.
+ * Copyright 2009, 2019 Technical University Berlin, Germany.
  * 
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -18,6 +18,8 @@
 import static org.eclipse.objectteams.otequinox.Constants.*;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -35,6 +37,14 @@
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.dom.IBinding;
+import org.eclipse.jdt.core.dom.IMethodBinding;
+import org.eclipse.jdt.core.dom.IMethodMappingBinding;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.internal.corext.dom.Bindings;
+import org.eclipse.objectteams.otdt.core.IMethodMapping;
 import org.eclipse.objectteams.otdt.core.IRoleType;
 import org.eclipse.objectteams.otdt.core.OTModelManager;
 import org.eclipse.objectteams.otdt.internal.pde.ui.OTPDEUIMessages;
@@ -159,6 +169,8 @@
 		@SuppressWarnings("decapsulation")
 		int getLine(Element element, String attrName) -> int getLine(Element element, String attrName);
 
+		VirtualMarker report(String message, int line, int severity, int fixId, Element element, String attrName, String category)
+		<- replace VirtualMarker report(String message, int line, int severity, int fixId, Element element, String attrName, String category);
 
 		void checkAspectBinding(Element element) <- after void validateExtension(Element element);
 
@@ -171,6 +183,8 @@
 				// it's an aspect bundle
 				context.isAspectBundle = true;
 				
+				IJavaProject jProject = JavaCore.create(context.getProject());
+
 				boolean hasSelfAdaptation = false;
 				NodeList baseNodes = element.getElementsByTagName(BASE_PLUGIN);
 				for (int b=0; b<baseNodes.getLength(); b++) {
@@ -180,15 +194,21 @@
 					}
 				}
 
-				// collect binding requirements by nested teams of all bound teams:
-				NodeList teamNodes = element.getElementsByTagName(TEAM);
-				for (int t=0; t<teamNodes.getLength(); t++) {
-					// record aspect packages:
-					Object teamClass = ((Element)teamNodes.item(t)).getAttribute(CLASS);
-					if (teamClass instanceof String)
-						checkNestedTeams((String) teamClass, context, hasSelfAdaptation);
+				Map<String,Set<String>> superBasePackagesByTeam;
+				{
+					List<IMethodMapping> mappings = new ArrayList<>();
+	
+					// collect binding requirements by nested teams of all bound teams:
+					NodeList teamNodes = element.getElementsByTagName(TEAM);
+					for (int t=0; t<teamNodes.getLength(); t++) {
+						// record aspect packages:
+						Object teamClass = ((Element)teamNodes.item(t)).getAttribute(CLASS);
+						if (teamClass instanceof String)
+							checkNestedTeams((String) teamClass, context, hasSelfAdaptation, mappings);
+					}
+					// collect packages with overridden base methods:
+					superBasePackagesByTeam = collectOverridden(mappings);
 				}
-
 				NodeList aspectBindings = element.getChildNodes();
 				int aspectCount = aspectBindings.getLength();
 				for (int i = 0; i < aspectCount; i++) {
@@ -219,16 +239,18 @@
 								// analyze aspect packages:
 								Element teamNode = childElement;
 								Object teamClass = teamNode.getAttribute(CLASS);
-								if (teamClass instanceof String) {
-									String teamName = (String) teamClass;
-									String actualPackage = checkActualPackage(context, teamNode, teamName);
-									if (actualPackage == null)
-										report(OTPDEUIMessages.Validation_MissingPackage_error, getLine(teamNode),
-												CompilerFlags.ERROR, PDEMarkerFactory.NO_RESOLUTION, PDEMarkerFactory.CAT_FATAL);
-									else
-										context.aspectPackages.add(actualPackage);
-									teamNames.add(teamName);
-								}
+								if (!(teamClass instanceof String))
+									continue;
+							
+								String teamName = (String) teamClass;
+								String actualPackage = checkActualPackage(context, teamNode, teamName);
+								if (actualPackage == null)
+									report(OTPDEUIMessages.Validation_MissingPackage_error, getLine(teamNode),
+											CompilerFlags.ERROR, PDEMarkerFactory.NO_RESOLUTION, PDEMarkerFactory.CAT_FATAL);
+								else
+									context.aspectPackages.add(actualPackage);
+								teamNames.add(teamName);
+
 								// team activation?
 								Object activation = teamNode.getAttribute(ACTIVATION);
 								if (ActivationKind.ALL_THREADS.toString().equals(activation)) {
@@ -236,6 +258,14 @@
 								} else if (ActivationKind.THREAD.toString().equals(activation)) {
 									hasActivation = true;
 								}
+								NodeList superBases = teamNode.getElementsByTagName(SUPER_BASE);
+								for (int k=0; k<superBases.getLength(); k++) {
+									// report bad declarations & remove superBase requirements matching this declaration 
+									Node grandChild = superBases.item(k);
+									if (grandChild instanceof Element) {
+										checkSuperBaseClass((Element) grandChild, superBasePackagesByTeam.get(teamName), jProject, baseBundle);
+									}
+								}
 							}
 						}
 					}
@@ -262,21 +292,113 @@
 					}
 				}
 				// complain about remaining requiredBasePackages (i.e., those for which no binding was provided)
-				for (Entry<String, List<String>> entry : context.requiredBasePackagesPerTeam.entrySet()) {
-					List<String> requiredBasePackages = entry.getValue();
-					if (requiredBasePackages != null && !requiredBasePackages.isEmpty()) {
-						for (String requiredBasePackage : requiredBasePackages) {
-							report(NLS.bind(OTPDEUIMessages.Validation_MissingBindingForBasePackage_error, entry.getKey(), requiredBasePackage),
-									getLine(element), 
-									CompilerFlags.ERROR,
-									PDEMarkerFactory.NO_RESOLUTION,
-									PDEMarkerFactory.CAT_FATAL);
-						}
+				reportUnmatchedRequirements(element, context.requiredBasePackagesPerTeam,
+											OTPDEUIMessages.Validation_MissingBindingForBasePackage_error);
+				// complain about remaining undeclared super bases:
+				reportUnmatchedRequirements(element, superBasePackagesByTeam,
+											OTPDEUIMessages.Validation_MissingSuperBasePackageDecl_error);
+			}
+		}
 
+		private void reportUnmatchedRequirements(Element element,
+				Map<String, ? extends Collection<String>> packagesPerTeam,
+				String errorMessageTemplate)
+		{
+			for (Entry<String, ? extends Collection<String>> entry : packagesPerTeam.entrySet()) {
+				Collection<String> requiredBasePackages = entry.getValue();
+				if (requiredBasePackages != null && !requiredBasePackages.isEmpty()) {
+					for (String requiredBasePackage : requiredBasePackages) {
+						report(NLS.bind(errorMessageTemplate, entry.getKey(), requiredBasePackage),
+								getLine(element),
+								CompilerFlags.ERROR,
+								PDEMarkerFactory.NO_RESOLUTION,
+								PDEMarkerFactory.CAT_FATAL);
 					}
 				}
 			}
 		}
+
+		private Map<String, Set<String>> collectOverridden(List<IMethodMapping> mappings) {
+			Map<String,Set<String>> superBasePackagesByTeam = new HashMap<>();
+			try {
+				// collect role types from mappings (IType, then ITypeBinding):
+				Set<IType> roleTypes = new HashSet<IType>(); 
+				for (IMethodMapping mapping : mappings) {
+					IType type = mapping.getDeclaringType();
+					if (!"java.lang.Object".equals(type.getSuperclassName())) //$NON-NLS-1$
+						roleTypes.add(type);
+				}
+				if (roleTypes.isEmpty())
+					return Collections.emptyMap();
+				ASTParser parser = ASTParser.newParser(AST.JLS12);
+				parser.setProject(JavaCore.create(getFProject()));
+				IBinding[] bindings = parser.createBindings(roleTypes.toArray(new IType[roleTypes.size()]), null);
+
+				// from ITypeBinding descend into IMethodMappingBinding, then IMethodBinding (base):
+				for (IBinding binding : bindings) {
+					if (binding instanceof ITypeBinding) {
+						String teamName = ((ITypeBinding) binding).getDeclaringClass().getQualifiedName();
+						Set<String> perTeamResult = superBasePackagesByTeam.get(teamName);
+						for (IMethodMappingBinding mappingBinding : ((ITypeBinding) binding).getResolvedMethodMappings()) {
+							for (IMethodBinding basemethod : mappingBinding.getBaseMethods()) {
+								// find overridden
+								IMethodBinding overriddenMethod = Bindings.findOverriddenMethod(basemethod, true);
+								if (overriddenMethod != null) {
+									// remember package of declaring class
+									String packageName = overriddenMethod.getDeclaringClass().getPackage().getName();
+									if (perTeamResult == null) {
+										superBasePackagesByTeam.put(teamName, perTeamResult = new HashSet<>());
+									}
+									perTeamResult.add(packageName);
+								}
+							}
+						}
+					}
+				}
+			} catch (JavaModelException e) {
+				// cannot analyse
+			}
+			return superBasePackagesByTeam;
+		}
+
+		private void checkSuperBaseClass(Element elem, Set<String> collectedPackages, IJavaProject jProject, BundleDescription baseBundle) {
+			try {
+				String packageName = null;
+				String superBaseClass = elem.getAttribute(SUPER_BASE_CLASS);
+				if (superBaseClass != null) {
+					IType clazz = jProject.findType(superBaseClass);
+					if (clazz != null) { // otherwise assume standard validation already complained
+						packageName = clazz.getPackageFragment().getElementName();
+						if (collectedPackages == null || !collectedPackages.remove(packageName)) {
+							report(NLS.bind(OTPDEUIMessages.Validation_UnnecessarySuperBase_warning, superBaseClass),
+									getLine(elem), 
+									CompilerFlags.WARNING,
+									PDEMarkerFactory.NO_RESOLUTION,
+									PDEMarkerFactory.CAT_OTHER);
+						}
+					}
+				}
+				if (packageName != null) {
+					String bundleName = elem.getAttribute(SUPER_BASE_PLUGIN);
+					BundleDescription basePlugIn = (bundleName != null) ? checkBasePlugIn(bundleName, getLine(elem))
+													: baseBundle; // fall back if no explicit plugin
+					if (basePlugIn != null) {
+						for (Capability cap : basePlugIn.getCapabilities(PackageNamespace.PACKAGE_NAMESPACE)) {
+							if (packageName.equals(cap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE)))
+								return;
+						}
+						report(NLS.bind(OTPDEUIMessages.Validation_PackageNotInSuperBase_error, bundleName, packageName),
+								getLine(elem), 
+								CompilerFlags.ERROR,
+								PDEMarkerFactory.NO_RESOLUTION,
+								PDEMarkerFactory.CAT_FATAL);						
+					}
+				}
+			} catch (JavaModelException e) {
+				// cannot analyse
+			}
+		}
+
 		String checkActualPackage(BundleCheckingContext context, Element teamNode, String teamName) {
 			int lastDot = teamName.lastIndexOf('.');
 			if (lastDot == -1)
@@ -333,7 +455,7 @@
 			return bundles[0];
 		}
 		
-		void checkNestedTeams(String teamName, BundleCheckingContext context, boolean hasSelfAdaptation) {
+		void checkNestedTeams(String teamName, BundleCheckingContext context, boolean hasSelfAdaptation, List<IMethodMapping> mappings) {
 			teamName = teamName.replace('$', '.');
 			IJavaProject jPrj = JavaCore.create(getFProject());
 			if (jPrj.exists()) {
@@ -349,7 +471,11 @@
 											&& !(hasSelfAdaptation && aBase.getJavaProject().equals(jPrj)))
 										context.addRequiredBasePackage(nestedTeamName, aBase.getPackageFragment().getElementName());
 								}
-								checkNestedTeams(nestedTeamName, context, hasSelfAdaptation);
+								checkNestedTeams(nestedTeamName, context, hasSelfAdaptation, mappings);
+							} else {
+								IRoleType role = (IRoleType) OTModelManager.getOTElement(member);
+								for (IMethodMapping mapping : role.getMethodMappings())
+									mappings.add(mapping);
 							}
 						}
 					}
@@ -358,6 +484,26 @@
 				}
 			}
 		}
+
+		@SuppressWarnings("basecall")
+		callin VirtualMarker report(String message, int line, int severity, int fixId, Element element, String attrName, String category) {
+			if (fixId == PDEMarkerFactory.M_DISCOURAGED_CLASS) {
+				if (matchElementPath(element, new String[] {ASPECT_BINDING, TEAM, SUPER_BASE}, 2))
+					return null; // don't report restriction inside aspectBinding/superBase
+			}
+			return base.report(message, line, severity, fixId, element, attrName, category);
+		}
+
+		private boolean matchElementPath(Element cur, String[] containerTags, int idx) {
+			if (idx < 0)
+				return true;
+			if (!containerTags[idx].equals(cur.getTagName()))
+				return false;
+			Node parentNode = cur.getParentNode();
+			if (parentNode instanceof Element)
+				return matchElementPath((Element) parentNode, containerTags, idx-1);
+			return false;
+		}
 	}
 	
 	/**
diff --git a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/Constants.java b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/Constants.java
index 6513d73..ae04c5a 100644
--- a/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/Constants.java
+++ b/plugins/org.eclipse.objectteams.otequinox/src/org/eclipse/objectteams/otequinox/Constants.java
@@ -34,6 +34,7 @@
 	/** Simple name of the extension point org.eclipse.objectteams.otequinox.aspectBindings. */
 	static final String ASPECT_BINDING_EXTPOINT_ID    = "aspectBindings";
 	static final String ASPECT_BINDING_FQEXTPOINT_ID  = TRANSFORMER_PLUGIN_ID+'.'+ASPECT_BINDING_EXTPOINT_ID;
+	static final String ASPECT_BINDING = "aspectBinding";
 	
 	/** Simple name of the extension point org.eclipse.objectteams.otequinox.liftingParticipant. */
 	static final String LIFTING_PARTICIPANT_EXTPOINT_ID    = "liftingParticipant";
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/src/org/eclipse/objectteams/otdt/test/builder/OTEquinoxBuilderTests.java b/testplugins/org.eclipse.objectteams.otdt.test.builder/src/org/eclipse/objectteams/otdt/test/builder/OTEquinoxBuilderTests.java
index 68ff016..d554f67 100644
--- a/testplugins/org.eclipse.objectteams.otdt.test.builder/src/org/eclipse/objectteams/otdt/test/builder/OTEquinoxBuilderTests.java
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/src/org/eclipse/objectteams/otdt/test/builder/OTEquinoxBuilderTests.java
@@ -1,7 +1,7 @@
 /**********************************************************************
  * This file is part of "Object Teams Development Tooling"-Software
  * 
- * Copyright 2004, 2010 Fraunhofer Gesellschaft, Munich, Germany,
+ * Copyright 2004, 2019 Fraunhofer Gesellschaft, Munich, Germany,
  * for its Fraunhofer Institute and Computer Architecture and Software
  * Technology (FIRST), Berlin, Germany and Technical University Berlin,
  * Germany.
@@ -48,6 +48,10 @@
 @SuppressWarnings({ "nls", "restriction" })
 public class OTEquinoxBuilderTests extends OTBuilderTests {
 
+	static {
+//		TESTS_NAMES = new String[] { "testBug494254"};
+	}
+
 	MyFileBasedTest fileManager= new MyFileBasedTest("delegate");
 	class MyFileBasedTest extends FileBasedTest {
 		public MyFileBasedTest(String name) {
@@ -84,10 +88,7 @@
 			destFile.setContents(new FileInputStream(srcFile), true, false, null);
 		}
 	};
-	
-	static {
-//		TESTS_NAMES = new String[] { "testBug419987"};
-	}
+
 	public OTEquinoxBuilderTests(String name) {
 		super(name);
 	}
@@ -431,6 +432,38 @@
 		expectingNoProblemsFor(aspPrj.getPath());
 	}
 
+	public void testBug494254() throws CoreException, IOException {
+		IJavaProject basePrj0= fileManager.setUpJavaProject("Bug494254base0"); 
+		env.addProject(basePrj0.getProject());
+		IJavaProject basePrj1= fileManager.setUpJavaProject("Bug494254base1"); 
+		env.addProject(basePrj1.getProject());
+		IJavaProject aspPrj= fileManager.setUpJavaProject("Bug494254aspect"); 
+		env.addProject(aspPrj.getProject());
+		fullBuild();
+		expectingNoProblemsFor(basePrj0.getPath());
+		expectingNoProblemsFor(basePrj1.getPath());
+		expectingOnlySpecificProblemsFor(aspPrj.getPath(), new Problem[] {
+			new Problem("", "Team 'bug494254aspect.Team1' lacks a superBase declaration for base class 'p0'",
+					aspPrj.getPath().append(new Path("plugin.xml")),
+						-1, -1, -1, IMarker.SEVERITY_ERROR),
+			new Problem("", "Plug-in 'Bug494254base0' does not provide package 'p1'",
+					aspPrj.getPath().append("plugin.xml"),
+						-1, -1, -1, IMarker.SEVERITY_ERROR),
+			new Problem("", "Unnecessary superBase declaration 'p0.C0'",
+					aspPrj.getPath().append("plugin.xml"),
+						-1, -1, -1, IMarker.SEVERITY_WARNING),
+			new Problem("", "Unnecessary superBase declaration 'p1.C1'",
+					aspPrj.getPath().append("plugin.xml"),
+						-1, -1, -1, IMarker.SEVERITY_WARNING)
+		});
+		// repair and check absence of problems:
+		IFile normal = (IFile) aspPrj.getProject().findMember("plugin.xml");
+		IFile ok = (IFile) aspPrj.getProject().findMember("plugin-ok.xml");
+		normal.setContents(ok.getContents(), 0, null);
+		fullBuild();
+		expectingNoProblemsFor(aspPrj.getPath());
+	}
+
 	// ---------------- HELPERS: ---------------------------
 	private Problem getDecapsulationProblem(IJavaProject project, String baseclassName, String teamPath, int start, int end) {
 		return new Problem("", "Decapsulating base class "+baseclassName+" by means of a forced export. Note, that additionally a corresponing declaration is needed in config.ini (OTJLD 2.1.2(c) + OT/Equinox).",
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/.classpath b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/.classpath
new file mode 100644
index 0000000..23cc98b
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="OTRE"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/.project b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/.project
new file mode 100644
index 0000000..40d26df
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/.project
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Bug494254aspect</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.objectteams.otdt.builder.OTJBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.objectteams.otdt.OTJavaNature</nature>
+	</natures>
+</projectDescription>
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/.settings/org.eclipse.jdt.core.prefs b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..3ffc382
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,28 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.objectteams.otdt.compiler.option.pure_java=enabled
+org.eclipse.objectteams.otdt.compiler.option.weaving_scheme=OTDRE
+org.eclipse.objectteams.otdt.compiler.problem.abstract_potential_relevant_role=warning
+org.eclipse.objectteams.otdt.compiler.problem.adapting_deprecated=error
+org.eclipse.objectteams.otdt.compiler.problem.ambiguous_lowering=warning
+org.eclipse.objectteams.otdt.compiler.problem.basecall=warning
+org.eclipse.objectteams.otdt.compiler.problem.baseclass_cycle=warning
+org.eclipse.objectteams.otdt.compiler.problem.binding_conventions=error
+org.eclipse.objectteams.otdt.compiler.problem.decapsulation=warning
+org.eclipse.objectteams.otdt.compiler.problem.decapsulation_write=warning
+org.eclipse.objectteams.otdt.compiler.problem.deprecated_path_syntax=warning
+org.eclipse.objectteams.otdt.compiler.problem.effectless_fieldaccess=warning
+org.eclipse.objectteams.otdt.compiler.problem.exception_in_guard=error
+org.eclipse.objectteams.otdt.compiler.problem.fragile_callin=warning
+org.eclipse.objectteams.otdt.compiler.problem.ignoring_role_return=warning
+org.eclipse.objectteams.otdt.compiler.problem.inferred_callout=error
+org.eclipse.objectteams.otdt.compiler.problem.override_final_role=error
+org.eclipse.objectteams.otdt.compiler.problem.potential_ambiguous_playedby=warning
+org.eclipse.objectteams.otdt.compiler.problem.unsafe_role_instantiation=warning
+org.eclipse.objectteams.otdt.compiler.problem.unused_parammap=warning
+org.eclipse.objectteams.otdt.compiler.problem.weave_into_system_class=warning
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/META-INF/MANIFEST.MF b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..70e03c4
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/META-INF/MANIFEST.MF
@@ -0,0 +1,11 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Bug494254aspect
+Bundle-SymbolicName: Bug494254aspect;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Require-Bundle: org.eclipse.objectteams.otequinox,
+ Bug494254base1;bundle-version="1.0.0"
+Automatic-Module-Name: Bug494254aspect
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
+Export-Package: bug494254aspect
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/build.properties b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/build.properties
new file mode 100644
index 0000000..e9863e2
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/plugin-ok.xml b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/plugin-ok.xml
new file mode 100644
index 0000000..10c4f9f
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/plugin-ok.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+   <extension
+         point="org.eclipse.objectteams.otequinox.aspectBindings">
+      <aspectBinding
+            icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/calloutbinding_obj.gif">
+         <basePlugin
+               icon="platform:/plugin/org.eclipse.pde.ui/icons/obj16/plugin_obj.png"
+               id="Bug494254base1">
+         </basePlugin>
+         <team
+               class="bug494254aspect.Team1"
+               icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif">
+               <superBase class="p0.C0" plugin="Bug494254base0"/>
+         </team>
+         <team
+               class="bug494254aspect.Team2"
+               icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif">
+         </team>
+      </aspectBinding>
+   </extension>
+</plugin>
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/plugin.xml b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/plugin.xml
new file mode 100644
index 0000000..39a61e1
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/plugin.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+   <extension
+         point="org.eclipse.objectteams.otequinox.aspectBindings">
+      <aspectBinding
+            icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/calloutbinding_obj.gif">
+         <basePlugin
+               icon="platform:/plugin/org.eclipse.pde.ui/icons/obj16/plugin_obj.png"
+               id="Bug494254base1">
+         </basePlugin>
+         <team
+               class="bug494254aspect.Team1"
+               icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif">
+         </team>
+         <team
+               class="bug494254aspect.Team2"
+               icon="platform:/plugin/org.eclipse.objectteams.otdt.ui/icons/ot/team_obj.gif">
+             <superBase class="p0.C0" plugin="Bug494254base0"/>
+             <superBase class="p1.C1" plugin="Bug494254base0"/>
+         </team>
+      </aspectBinding>
+   </extension>
+</plugin>
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/src/bug494254aspect/Team1.java b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/src/bug494254aspect/Team1.java
new file mode 100644
index 0000000..5b26264
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/src/bug494254aspect/Team1.java
@@ -0,0 +1,13 @@
+package bug494254aspect;
+
+import base p1.C1;
+
+public team class Team1 {
+	protected class R playedBy C1 {
+		void getName(int i) <- before String getName(int i);
+
+		private void getName(int i) {
+			System.out.println("intercepted");
+		}
+	}
+}
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/src/bug494254aspect/Team2.java b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/src/bug494254aspect/Team2.java
new file mode 100644
index 0000000..5d5ce15
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254aspect/src/bug494254aspect/Team2.java
@@ -0,0 +1,13 @@
+package bug494254aspect;
+
+import base p1.C1;
+
+public team class Team2 {
+	protected class R playedBy C1 {
+		void getName(int i) <- before String method2(int i);
+
+		private void getName(int i) {
+			System.out.println("intercepted");
+		}
+	}
+}
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/.classpath b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/.classpath
new file mode 100644
index 0000000..eca7bdb
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/.project b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/.project
new file mode 100644
index 0000000..2514940
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Bug494254base0</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/.settings/org.eclipse.jdt.core.prefs b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..68cbd3a
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.objectteams.otdt.compiler.option.pure_java=enabled
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/META-INF/MANIFEST.MF b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..07173f9
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/META-INF/MANIFEST.MF
@@ -0,0 +1,8 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Base0_494254
+Bundle-SymbolicName: Bug494254base0
+Bundle-Version: 1.0.0.qualifier
+Automatic-Module-Name: Base0_494254
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Export-Package: p0;x-friends:="Bug494254base1"
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/build.properties b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/build.properties
new file mode 100644
index 0000000..34d2e4d
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/src/p0/C0.java b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/src/p0/C0.java
new file mode 100644
index 0000000..7775765
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base0/src/p0/C0.java
@@ -0,0 +1,7 @@
+package p0;
+
+public class C0 {
+	protected String getName(int i) {
+		return Integer.toString(i);
+	}
+}
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/.classpath b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/.classpath
new file mode 100644
index 0000000..eca7bdb
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/.project b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/.project
new file mode 100644
index 0000000..79e19b5
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Bug494254base1</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/.settings/org.eclipse.jdt.core.prefs b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..68cbd3a
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.objectteams.otdt.compiler.option.pure_java=enabled
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/META-INF/MANIFEST.MF b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..8e2230f
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/META-INF/MANIFEST.MF
@@ -0,0 +1,9 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Base1_494254
+Bundle-SymbolicName: Bug494254base1
+Bundle-Version: 1.0.0.qualifier
+Automatic-Module-Name: Base1_494254
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: Bug494254base0;bundle-version="1.0.0";visibility:=reexport
+Export-Package: p1
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/build.properties b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/build.properties
new file mode 100644
index 0000000..34d2e4d
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
diff --git a/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/src/p1/C1.java b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/src/p1/C1.java
new file mode 100644
index 0000000..12c592f
--- /dev/null
+++ b/testplugins/org.eclipse.objectteams.otdt.test.builder/workspace/Bug494254base1/src/p1/C1.java
@@ -0,0 +1,13 @@
+package p1;
+
+import p0.C0;
+
+public class C1 extends C0 {
+	@Override
+	protected String getName(int i) {
+		return super.getName(i*2);
+	}
+	protected String method2(int i) {
+		return "nothing";
+	}
+}