Bug 494254 - Validation for superBase declarations in aspectBindings

- filter callout to public
- do show super base *class* names
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 40b8836..c2a6523 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
@@ -264,6 +264,10 @@
 
 	this.tagBits |= TagBits.KnowsDefaultAbstractMethods;
 	if (isClass() && isAbstract()) {
+//{ObjectTeams: kludge for missing session support from ASTParser.createBindings:
+		if (this.scope == null)
+			return;
+// SH}
 		if (this.scope.compilerOptions().targetJDK >= ClassFileConstants.JDK1_2)
 			return; // no longer added for post 1.2 targets
 
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 323a99a..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,7 +15,7 @@
 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 a base class in 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}''
 
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 dcbd913..d261984 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
@@ -27,11 +27,14 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.Path;
+import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IType;
@@ -194,7 +197,7 @@
 					}
 				}
 
-				Map<String,Set<String>> superBasePackagesByTeam;
+				Map<String,Map<String,Set<String>>> superBasePackagesByTeam;
 				{
 					List<IMethodMapping> mappings = new ArrayList<>();
 	
@@ -292,23 +295,25 @@
 					}
 				}
 				// complain about remaining requiredBasePackages (i.e., those for which no binding was provided)
-				reportUnmatchedRequirements(element, context.requiredBasePackagesPerTeam,
+				reportUnmatchedRequirements(element, context.requiredBasePackagesPerTeam, e->e,
 											OTPDEUIMessages.Validation_MissingBindingForBasePackage_error);
 				// complain about remaining undeclared super bases:
 				reportUnmatchedRequirements(element, superBasePackagesByTeam,
+											e->e.values().stream().flatMap(Set::stream).collect(Collectors.toSet()),
 											OTPDEUIMessages.Validation_MissingSuperBasePackageDecl_error);
 			}
 		}
 
-		private void reportUnmatchedRequirements(Element element,
-				Map<String, ? extends Collection<String>> packagesPerTeam,
+		private <T> void reportUnmatchedRequirements(Element element,
+				Map<String, T> requirementsPerTeam,
+				Function<T,? extends Collection<String>> extractor,
 				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),
+			for (Entry<String, T> entry : requirementsPerTeam.entrySet()) {
+				Collection<String> requireds = extractor.apply(entry.getValue());
+				if (requireds != null && !requireds.isEmpty()) {
+					for (String required : requireds) {
+						report(NLS.bind(errorMessageTemplate, entry.getKey(), required),
 								getLine(element),
 								CompilerFlags.ERROR,
 								PDEMarkerFactory.NO_RESOLUTION,
@@ -318,8 +323,8 @@
 			}
 		}
 
-		private Map<String, Set<String>> collectOverridden(List<IMethodMapping> mappings) {
-			Map<String,Set<String>> superBasePackagesByTeam = new HashMap<>();
+		private Map<String, Map<String,Set<String>>> collectOverridden(List<IMethodMapping> mappings) {
+			Map<String,Map<String,Set<String>>> superBasePackagesByTeam = new HashMap<>(); // inner map is package name -> class names
 			try {
 				// collect role types from mappings (IType, then ITypeBinding):
 				Set<IType> roleTypes = new HashSet<IType>(); 
@@ -338,17 +343,24 @@
 				for (IBinding binding : bindings) {
 					if (binding instanceof ITypeBinding) {
 						String teamName = ((ITypeBinding) binding).getDeclaringClass().getQualifiedName();
-						Set<String> perTeamResult = superBasePackagesByTeam.get(teamName);
+						Map<String,Set<String>> perTeamResult = superBasePackagesByTeam.get(teamName);
 						for (IMethodMappingBinding mappingBinding : ((ITypeBinding) binding).getResolvedMethodMappings()) {
 							for (IMethodBinding basemethod : mappingBinding.getBaseMethods()) {
+								if (!mappingBinding.isCallin() && Flags.isPublic(basemethod.getModifiers()))
+									continue; // no weaving required for callout to public
 								// find overridden
 								for (IMethodBinding overriddenMethod : Bindings.findOverriddenMethods(basemethod, true, false)) {									
 									// remember package of declaring class
-									String packageName = overriddenMethod.getDeclaringClass().getPackage().getName();
+									ITypeBinding declaringClass = overriddenMethod.getDeclaringClass();
+									String packageName = declaringClass.getPackage().getName();
 									if (perTeamResult == null) {
-										superBasePackagesByTeam.put(teamName, perTeamResult = new HashSet<>());
+										superBasePackagesByTeam.put(teamName, perTeamResult = new HashMap<>());
 									}
-									perTeamResult.add(packageName);
+									Set<String> classSet = perTeamResult.get(packageName);
+									if (classSet == null) {
+										perTeamResult.put(packageName, classSet = new HashSet<>());
+									}
+									classSet.add(declaringClass.getQualifiedName());
 								}
 							}
 						}
@@ -360,7 +372,7 @@
 			return superBasePackagesByTeam;
 		}
 
-		private void checkSuperBaseClass(Element elem, Set<String> collectedPackages, IJavaProject jProject, BundleDescription baseBundle) {
+		private void checkSuperBaseClass(Element elem, Map<String,Set<String>> collectedPackages, IJavaProject jProject, BundleDescription baseBundle) {
 			try {
 				String packageName = null;
 				String superBaseClass = elem.getAttribute(SUPER_BASE_CLASS);
@@ -368,7 +380,7 @@
 					IType clazz = jProject.findType(superBaseClass);
 					if (clazz != null) { // otherwise assume standard validation already complained
 						packageName = clazz.getPackageFragment().getElementName();
-						if (collectedPackages == null || !collectedPackages.remove(packageName)) {
+						if (collectedPackages == null || collectedPackages.remove(packageName) == null) {
 							report(NLS.bind(OTPDEUIMessages.Validation_UnnecessarySuperBase_warning, superBaseClass),
 									getLine(elem), 
 									CompilerFlags.WARNING,
@@ -379,7 +391,7 @@
 				}
 				if (packageName != null) {
 					String bundleName = elem.getAttribute(SUPER_BASE_PLUGIN);
-					BundleDescription basePlugIn = (bundleName != null) ? checkBasePlugIn(bundleName, getLine(elem))
+					BundleDescription basePlugIn = !bundleName.isEmpty() ? checkBasePlugIn(bundleName, getLine(elem))
 													: baseBundle; // fall back if no explicit plugin
 					if (basePlugIn != null) {
 						for (Capability cap : basePlugIn.getCapabilities(PackageNamespace.PACKAGE_NAMESPACE)) {
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 6b4c02e..253466f 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
@@ -443,7 +443,7 @@
 		expectingNoProblemsFor(basePrj0.getPath());
 		expectingNoProblemsFor(basePrj1.getPath());
 		expectingOnlySpecificProblemsFor(aspPrj.getPath(), new Problem[] {
-			new Problem("", "Team 'bug494254aspect.Team1' lacks a superBase declaration for a base class in package 'p0'",
+			new Problem("", "Team 'bug494254aspect.Team1' lacks a superBase declaration for base class 'p0.C0'",
 					aspPrj.getPath().append(new Path("plugin.xml")),
 						-1, -1, -1, IMarker.SEVERITY_ERROR),
 			new Problem("", "Plug-in 'Bug494254base0' does not provide package 'p1'",