Test & fix for Bug 370273 - [compiler][otjld] consider allowing base
imported types as the return type of a team method
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedSingleTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedSingleTypeReference.java
index 08acfc2..0af1cb8 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedSingleTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedSingleTypeReference.java
@@ -34,8 +34,8 @@
}
//{ObjectTeams: one more method to override:
@Override
- public TypeBinding checkResolveUsingBaseImportScope(Scope scope) {
- TypeBinding result = super.checkResolveUsingBaseImportScope(scope);
+ public TypeBinding checkResolveUsingBaseImportScope(Scope scope, boolean tolerate) {
+ TypeBinding result = super.checkResolveUsingBaseImportScope(scope, tolerate);
if (this.resolvedType != null)
throw new SelectionNodeFound(this.resolvedType);
return result;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
index 771e687..31ce927 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
@@ -110,7 +110,9 @@
ALLOWED { public boolean isAllowed() { return true; }},
/** This node is either a playedBy reference for which decapsulation has been reported,
* or some other (generated) base reference for which decapsulation shall not be reported. */
- REPORTED { public boolean isAllowed() { return true; }};
+ REPORTED { public boolean isAllowed() { return true; }},
+ /** This mode is for team method return types: prefer local resolution, but tolerate base class as a fallback. */
+ TOLERATED { public boolean isAllowed() { return false; }};
abstract public boolean isAllowed();
}
public DecapsulationState getBaseclassDecapsulation() {return DecapsulationState.NONE;}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
index 4c92765..c0e16b8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
@@ -449,9 +449,10 @@
//{ObjectTeams: resolve helpers
// for base-imported types (only single is supported):
@Override
- public TypeBinding checkResolveUsingBaseImportScope(Scope scope) {
+ public TypeBinding checkResolveUsingBaseImportScope(Scope scope, boolean tolerate) {
// same as in SingleTypeReference:
if ( this.getBaseclassDecapsulation().isAllowed()
+ || tolerate
|| scope.isBaseGuard())
{
TypeBinding problem = this.resolvedType;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
index 0e5b6be..5f8c0e1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
@@ -107,8 +107,9 @@
//{ObjectTeams: for base-imported types (only single is supported):
@Override
- public TypeBinding checkResolveUsingBaseImportScope(Scope scope) {
+ public TypeBinding checkResolveUsingBaseImportScope(Scope scope, boolean tolerate) {
if ( this.getBaseclassDecapsulation().isAllowed()
+ || tolerate
|| scope.isBaseGuard())
{
TypeBinding problem = this.resolvedType;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
index 89eba30..0a30535 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
@@ -167,7 +167,7 @@
CompilationResult compilationResult = scope.referenceCompilationUnit().compilationResult();
CompilationResult.CheckPoint cp = compilationResult.getCheckPoint(scope.referenceContext());
try {
- type = checkResolveUsingBaseImportScope(scope);
+ type = checkResolveUsingBaseImportScope(scope, false); // apply TOLERATE strategy only as a last resort below
// copied from below:
if (type != null && type.isValidBinding()) {
type = scope.environment().convertToRawType(type, false /*do not force conversion of enclosing types*/);
@@ -199,8 +199,8 @@
throw snf; // found a valid node.
caughtException = snf;
}
- try {
// a third chance trying an anchored type:
+ try {
if ( (caughtException != null)
|| (this.resolvedType.problemId() == ProblemReasons.NotFound))
{
@@ -211,11 +211,25 @@
}
} catch (SelectionNodeFound snf2) {
caughtException = snf2; // throw the newer exception instead.
- } finally {
+ }
+//a forth chance trying a TOLERATED base imported type:
+ try {
+ if ( (caughtException != null)
+ || (this.resolvedType.problemId() == ProblemReasons.NotFound))
+ {
+ if (this.baseclassDecapsulation == DecapsulationState.TOLERATED) {
+ TypeBinding result = checkResolveUsingBaseImportScope(scope, true);
+ if (result != null) // did we do any better than before?
+ type = this.resolvedType = result; // if non-null but ProblemBinding report below.
+ }
+ }
+ } catch (SelectionNodeFound snf2) {
+ caughtException = snf2; // throw the newer exception instead.
+ } finally {
// the attempt to prevent an exception failed:
if (caughtException != null)
throw caughtException;
- }
+ }
// SH}
if ((hasError = !type.isValidBinding()) == true) {
reportInvalidType(scope);
@@ -258,7 +272,7 @@
//{ObjectTeams: alternative strategies for resolving:
/** Try to resolve this reference from base imports. */
-public TypeBinding checkResolveUsingBaseImportScope(Scope scope) {
+public TypeBinding checkResolveUsingBaseImportScope(Scope scope, boolean tolerate) {
return null; // override to do something useful (only in SingleTypeReference).
}
/**
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index 5a69310..b82025b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -2369,7 +2369,7 @@
*/
typeReference.deprecationProblemId = IProblem.DeprecatedBaseclass;
ReferenceBinding superType;
- if (typeReference.checkResolveUsingBaseImportScope(this) != null) {
+ if (typeReference.checkResolveUsingBaseImportScope(this, false) != null) {
superType = (ReferenceBinding)typeReference.resolvedType;
} else {
superType = (ReferenceBinding) typeReference.resolveSuperType(this);
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 46f0bf1..07d1434 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
@@ -2268,6 +2268,8 @@
} else {
//{ObjectTeams: option to roll back problems:
CheckPoint cp = this.scope.referenceContext.compilationResult.getCheckPoint(methodDecl);
+ if (this.isTeam() && !method.isPrivate() && returnType.getBaseclassDecapsulation() == DecapsulationState.NONE)
+ returnType.setBaseclassDecapsulation(DecapsulationState.TOLERATED);
// SH}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=322817
boolean deferRawTypeCheck = !reportUnavoidableGenericTypeProblems && (returnType.bits & ASTNode.IgnoreRawTypeCheck) == 0;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/IAlienScopeTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/IAlienScopeTypeReference.java
index 7d2ccb5..15be70e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/IAlienScopeTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/util/IAlienScopeTypeReference.java
@@ -51,8 +51,8 @@
}
public Scope getAlienScope() { return this.alienScope; }
@Override
- public TypeBinding checkResolveUsingBaseImportScope(Scope scope) {
- return super.checkResolveUsingBaseImportScope(this.alienScope);
+ public TypeBinding checkResolveUsingBaseImportScope(Scope scope, boolean tolerate) {
+ return super.checkResolveUsingBaseImportScope(this.alienScope, tolerate);
}
@Override
public TypeBinding resolveType(ClassScope scope) {
@@ -87,8 +87,8 @@
}
public Scope getAlienScope() { return this.alienScope; }
@Override
- public TypeBinding checkResolveUsingBaseImportScope(Scope scope) {
- return super.checkResolveUsingBaseImportScope(this.alienScope);
+ public TypeBinding checkResolveUsingBaseImportScope(Scope scope, boolean tolerate) {
+ return super.checkResolveUsingBaseImportScope(this.alienScope, tolerate);
}
@Override
public TypeBinding resolveType(ClassScope scope) {
@@ -124,15 +124,15 @@
}
public Scope getAlienScope() { return this.alienScope; }
@Override
- public TypeBinding checkResolveUsingBaseImportScope(Scope scope) {
+ public TypeBinding checkResolveUsingBaseImportScope(Scope scope, boolean tolerate) {
// `scope` may be stronger then `alienScope`, try it first:
// (see 1.1.22-otjld-layered-teams-5)
- TypeBinding result= super.checkResolveUsingBaseImportScope(scope);
+ TypeBinding result= super.checkResolveUsingBaseImportScope(scope, tolerate);
if (result != null && result.isValidBinding())
return result;
// remove problem binding if any:
this.resolvedType = null;
- return super.checkResolveUsingBaseImportScope(this.alienScope);
+ return super.checkResolveUsingBaseImportScope(this.alienScope, tolerate);
}
@Override
public TypeBinding resolveType(ClassScope scope) {
@@ -168,8 +168,8 @@
}
public Scope getAlienScope() { return this.alienScope; }
@Override
- public TypeBinding checkResolveUsingBaseImportScope(Scope scope) {
- return super.checkResolveUsingBaseImportScope(this.alienScope);
+ public TypeBinding checkResolveUsingBaseImportScope(Scope scope, boolean tolerate) {
+ return super.checkResolveUsingBaseImportScope(this.alienScope, tolerate);
}
@Override
public TypeBinding resolveType(ClassScope scope) {
@@ -208,8 +208,8 @@
}
public Scope getAlienScope() { return this.alienScope; }
@Override
- public TypeBinding checkResolveUsingBaseImportScope(Scope scope) {
- return super.checkResolveUsingBaseImportScope(this.alienScope);
+ public TypeBinding checkResolveUsingBaseImportScope(Scope scope, boolean tolerate) {
+ return super.checkResolveUsingBaseImportScope(this.alienScope, tolerate);
}
@Override
public TypeBinding resolveType(ClassScope scope) {
diff --git a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/roleplaying/BaseClassVisibility.java b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/roleplaying/BaseClassVisibility.java
index e762d52..d846bfe 100644
--- a/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/roleplaying/BaseClassVisibility.java
+++ b/testplugins/org.eclipse.objectteams.otdt.tests/otjld/org/eclipse/objectteams/otdt/tests/otjld/roleplaying/BaseClassVisibility.java
@@ -30,7 +30,7 @@
// Static initializer to specify tests subset using TESTS_* static variables
// All specified tests which does not belong to the class are skipped...
static {
-// TESTS_NAMES = new String[] { "test242_inaccessibleBaseClass"};
+// TESTS_NAMES = new String[] { "test247_baseImportScope"};
// TESTS_NUMBERS = new int[] { 1459 };
// TESTS_RANGE = new int[] { 1097, -1 };
}
@@ -2128,4 +2128,106 @@
},
"Syntax error");
}
+
+ // a team uses a base-imported class as a return type for one of its methods
+ public void test247_baseImportScope4() {
+ runConformTest(
+ new String[] {
+ "T247bis4Main.java",
+ "public class T247bis4Main {\n" +
+ " public static void main(String... args) {\n" +
+ " System.out.print(new p2.Team247bis4().getR());\n" +
+ " }\n" +
+ "}\n",
+ "p2/Team247bis4.java",
+ "package p2;\n" +
+ "import base p1.T247bis4_1;\n" +
+ "public team class Team247bis4 {\n" +
+ " protected class R playedBy T247bis4_1 {\n" +
+ " protected R() {\n" +
+ " base();\n" +
+ " }\n" +
+ " }\n" +
+ " public T247bis4_1 getR() {\n" +
+ " return new R();\n" +
+ " }\n" +
+ "}\n",
+ "p1/T247bis4_1.java",
+ "\n" +
+ "package p1;\n" +
+ "public class T247bis4_1 {\n" +
+ " @Override public String toString() { return \"Base\"; }\n" +
+ "}\n"
+ },
+ "Base");
+ }
+ // resolving team method return type prefers role over base class
+ public void test247_baseImportScope5() {
+ runConformTest(
+ new String[] {
+ "T247bis5Main.java",
+ "public class T247bis5Main {\n" +
+ " public static void main(String... args) {\n" +
+ " new p2.Team247bis5().test();\n" +
+ " }\n" +
+ "}\n",
+ "p2/Team247bis5.java",
+ "package p2;\n" +
+ "import base p1.T247bis5_1;\n" +
+ "public team class Team247bis5 {\n" +
+ " protected class T247bis5_1 playedBy T247bis5_1 {\n" +
+ " protected T247bis5_1() { base(); }\n" +
+ " @Override public String toString() { return \"Role\"; }\n" +
+ " }\n" +
+ " T247bis5_1 getR() {\n" +
+ " return new T247bis5_1();\n" +
+ " }\n" +
+ " public void test() {\n" +
+ " System.out.print(getR());\n" +
+ " }\n" +
+ "}\n",
+ "p1/T247bis5_1.java",
+ "\n" +
+ "package p1;\n" +
+ "public class T247bis5_1 {\n" +
+ " @Override public String toString() { return \"Base\"; }\n" +
+ "}\n"
+ },
+ "Role");
+ }
+
+ // a team uses a base-imported class as a return type for one of its methods
+ // also: Bug 372391 - [compiler] creating bound role in field declaration throws NPE on role cache
+ public void _test247_baseImportScope6() {
+ runConformTest(
+ new String[] {
+ "T247bis6Main.java",
+ "public class T247bis6Main {\n" +
+ " public static void main(String... args) {\n" +
+ " System.out.print(new p2.Team247bis6().getR());\n" +
+ " }\n" +
+ "}\n",
+ "p2/Team247bis6.java",
+ "package p2;\n" +
+ "import base p1.T247bis6_1;\n" +
+ "public team class Team247bis6 {\n" +
+ " protected class R playedBy T247bis6_1 {\n" +
+ " protected R() {\n" +
+ " base();\n" +
+ " }\n" +
+ " }\n" +
+ " R r = new R();\n" +
+ " public T247bis6_1 getR() {\n" +
+ " return this.r;\n" +
+ " }\n" +
+ "}\n",
+ "p1/T247bis6_1.java",
+ "\n" +
+ "package p1;\n" +
+ "public class T247bis6_1 {\n" +
+ " @Override public String toString() { return \"Base\"; }\n" +
+ "}\n"
+ },
+ "Base");
+ }
}