diff options
author | Manoj Palat | 2015-08-27 05:02:25 +0000 |
---|---|---|
committer | Manoj Palat | 2015-08-27 05:03:13 +0000 |
commit | 74bb5893666ff64fec3acee561b65f591ab9aed2 (patch) | |
tree | 8c54d9328a693cd6afb3f21c14ed599f5cb175c3 | |
parent | c4d165337c4f39b38e6e47bd68ace1aa106b0673 (diff) | |
download | eclipse.jdt.core-74bb5893666ff64fec3acee561b65f591ab9aed2.tar.gz eclipse.jdt.core-74bb5893666ff64fec3acee561b65f591ab9aed2.tar.xz eclipse.jdt.core-74bb5893666ff64fec3acee561b65f591ab9aed2.zip |
Fix for Bug 470794 Missing support for Intersection types in
ITypeBinding
4 files changed, 131 insertions, 3 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java index c13eec8962..daa0e280a0 100644 --- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java +++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java @@ -5192,4 +5192,79 @@ public void test429813a() throws JavaModelException { assertTrue("Should be a varargs", binding.isVarargs());
}
+// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399792
+public void testBug470794_001() throws JavaModelException {
+ String content =
+ "public class X {\n" +
+ " Object o = (I & J) () -> {};" +
+ " public K main(Object o) {\n" +
+ " K oo = (I & J & K) o;\n" +
+ " return oo;\n" +
+ " }\n" +
+ "}\n" +
+ "interface I {\n" +
+ " public void foo();\n" +
+ "}\n" +
+ "interface J {\n" +
+ " public void foo();\n" +
+ " public void bar();\n" +
+ "}\n" +
+ "interface K {\n" +
+ " public void foo();\n" +
+ " public void bar();\n" +
+ "}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(content, this.workingCopy, true);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit unit = (CompilationUnit) node;
+ TypeDeclaration type = (TypeDeclaration) unit.types().get(0);
+ node = (ASTNode) type.bodyDeclarations().get(0);
+ assertEquals("Not a field Declaration", ASTNode.FIELD_DECLARATION, node.getNodeType());
+ FieldDeclaration field = (FieldDeclaration) node;
+ assertEquals("Field should not be malformed", 0, (field.getFlags() & ASTNode.MALFORMED));
+
+ List fragments = field.fragments();
+ assertEquals("Incorrect no of fragments", 1, fragments.size());
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0);
+ CastExpression cast = (CastExpression) fragment.getInitializer();
+ Type castType = cast.getType();
+ assertEquals("Not an intersection cast type", ASTNode.INTERSECTION_TYPE, castType.getNodeType());
+ assertTrue("Not an intersection cast type", castType.isIntersectionType());
+ assertEquals("Type should not be malformed", 0, (castType.getFlags() & ASTNode.MALFORMED));
+ ITypeBinding binding = castType.resolveBinding();
+ assertNotNull("binding is null", binding);
+ assertTrue("Not an intersection type binding", binding.isIntersectionType());
+ {
+ ITypeBinding [] intersectionBindings = binding.getTypeBounds();
+ String[] expectedTypes = new String[]{"I", "J"};
+ assertTrue("Incorrect number of intersection bindings", intersectionBindings.length == expectedTypes.length);
+ for (int i = 0, l = intersectionBindings.length; i < l; ++i) {
+ assertTrue("Unexpected Intersection Type", expectedTypes[i].equals(intersectionBindings[i].getName()));
+ }
+ }
+
+ node = (ASTNode) type.bodyDeclarations().get(1);
+ assertEquals("Not a method Declaration", ASTNode.METHOD_DECLARATION, node.getNodeType());
+ MethodDeclaration method = (MethodDeclaration) node;
+ assertEquals("Method should not be malformed", 0, (method.getFlags() & ASTNode.MALFORMED));
+
+ List statements = method.getBody().statements();
+ VariableDeclarationStatement statement = (VariableDeclarationStatement) statements.get(0);
+ fragment = (VariableDeclarationFragment) statement.fragments().get(0);
+ cast = (CastExpression) fragment.getInitializer();
+ castType = cast.getType();
+ binding = castType.resolveBinding();
+ assertNotNull("binding is null", binding);
+ assertTrue("Not an intersection type binding", binding.isIntersectionType());
+ {
+ ITypeBinding [] intersectionBindings = binding.getTypeBounds();
+ String[] expectedTypes = new String[]{"I", "J", "K"};
+ assertTrue("Incorrect number of intersection bindings", intersectionBindings.length == expectedTypes.length);
+ for (int i = 0, l = intersectionBindings.length; i < l; ++i) {
+ assertTrue("Unexpected Intersection Type", expectedTypes[i].equals(intersectionBindings[i].getName()));
+ }
+ }
+}
+
}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java index 4786097b39..64d8f26256 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java @@ -584,8 +584,8 @@ public interface ITypeBinding extends IBinding { public ITypeBinding[] getTypeArguments(); /** - * Returns the upper type bounds of this type variable, wildcard, or capture. If the - * variable, wildcard, or capture had no explicit bound, then it returns an empty list. + * Returns the upper type bounds of this type variable, wildcard, capture, or intersectionType. + * If the variable, wildcard, or capture had no explicit bound, then it returns an empty list. * <p> * Note that per construction, it can only contain one class or array type, * at most, and then it is located in first position. @@ -595,11 +595,12 @@ public interface ITypeBinding extends IBinding { * binding, e.g. <code>capture-of ? extends Object[]</code> * </p> * - * @return the list of upper bounds for this type variable, wildcard, or capture, + * @return the list of upper bounds for this type variable, wildcard, capture, or intersection type * or otherwise the empty list * @see #isTypeVariable() * @see #isWildcardType() * @see #isCapture() + * @see #isIntersectionType() * @since 3.1 */ public ITypeBinding[] getTypeBounds(); @@ -819,6 +820,28 @@ public interface ITypeBinding extends IBinding { public boolean isInterface(); /** + * Returns whether this type binding represents an intersection binding. + * <p> + * Intersection types can be derived from type parameter bounds and cast + * expressions; they also arise in the processes of capture conversion + * and least upper bound computation as specified in section 4.9 of + * <em>The Java Language Specification, Java SE 8 Edition</em> (JLS8). + * </p> + * <p> + * All the types in the intersection type can be accessed using + * {@link #getTypeBounds()}. Wildcard types with more than one + * bound will also be reported as intersection type. To check whether this + * is a wildcard type, use {@link #isWildcardType()}. + * </p> + * @return <code>true</code> if this type binding is an intersecting type, + * and <code>false</code> otherwise + * @see #getTypeBounds() + * @see ITypeBinding#isWildcardType() + * @since 3.12 + */ + public boolean isIntersectionType(); + + /** * Returns whether this type binding represents a local class. * <p> * A local class is any nested class or enum type not declared as a member diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java index c126584ef8..76c9bc70cc 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java @@ -467,6 +467,13 @@ class RecoveredTypeBinding implements ITypeBinding { } /* (non-Javadoc) + * @see org.eclipse.jdt.core.dom.ITypeBinding#isIntersectionType18() + */ + public boolean isIntersectionType() { + return false; + } + + /* (non-Javadoc) * @see org.eclipse.jdt.core.dom.ITypeBinding#isLocal() */ public boolean isLocal() { diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java index 1fdc50969d..1fd7224cf0 100644 --- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java +++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java @@ -554,6 +554,19 @@ class TypeBinding implements ITypeBinding { return this.interfaces = NO_TYPE_BINDINGS; } + private ITypeBinding[] getIntersectingTypes() { + ITypeBinding[] intersectionBindings = TypeBinding.NO_TYPE_BINDINGS; + if (this.binding instanceof IntersectionTypeBinding18) { + ReferenceBinding[] intersectingTypes = this.binding.getIntersectingTypes(); + int l = intersectingTypes.length; + intersectionBindings = new ITypeBinding[l]; + for (int i = 0; i < l; ++i) { + intersectionBindings[i] = this.resolver.getTypeBinding(intersectingTypes[i]); + } + } + return intersectionBindings; + } + public IJavaElement getJavaElement() { JavaElement element = getUnresolvedJavaElement(); if (element != null) @@ -926,6 +939,8 @@ class TypeBinding implements ITypeBinding { } else if (this.binding instanceof WildcardBinding) { WildcardBinding wildcardBinding = (WildcardBinding) this.binding; typeVariableBinding = wildcardBinding.typeVariable(); + } else if (this.binding instanceof IntersectionTypeBinding18) { + return this.bounds = getIntersectingTypes(); } if (typeVariableBinding != null) { ReferenceBinding varSuperclass = typeVariableBinding.superclass(); @@ -1214,6 +1229,14 @@ class TypeBinding implements ITypeBinding { } /* + * @see ITypeBinding#isIntersectionType18 + */ + public boolean isIntersectionType() { + int kind = this.binding.kind(); + return kind == Binding.INTERSECTION_TYPE18 || kind == Binding.INTERSECTION_TYPE; + } + + /* * @see ITypeBinding#isLocal() */ public boolean isLocal() { |