Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManoj Palat2013-04-23 05:35:41 +0000
committerJayaprakash Arthanareeswaran2013-04-23 05:35:41 +0000
commitd3d92e370789aaaed8a46c804d74e3cb2b4bb167 (patch)
treea14f4b0e3a0f327dc11f3030aa50ee313ad051c9
parente6029c8b1adfe1296ee554ed42f00e5a663cecbf (diff)
downloadeclipse.jdt.core-d3d92e370789aaaed8a46c804d74e3cb2b4bb167.tar.gz
eclipse.jdt.core-d3d92e370789aaaed8a46c804d74e3cb2b4bb167.tar.xz
eclipse.jdt.core-d3d92e370789aaaed8a46c804d74e3cb2b4bb167.zip
Fix for bug 404489 - [1.8][dom ast] Incorrect conversion of JSR308
TYPE_USE annotations on qualified name
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java36
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java364
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTMatcherTest.java12
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java4
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java1
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java21
-rw-r--r--org.eclipse.jdt.core.tests.model/workspace/Converter15/src/test404489/bug/X.java37
-rw-r--r--org.eclipse.jdt.core.tests.model/workspace/Converter18/src/test404489/bug/X.java37
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java23
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java167
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java25
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java10
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java30
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java6
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageQualifiedType.java285
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java9
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Type.java15
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java12
18 files changed, 1003 insertions, 91 deletions
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java
index 9c28c599d8..aec1a3c984 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java
@@ -5,6 +5,10 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
* Contributors:
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contributions for
@@ -11527,4 +11531,36 @@ public class ASTConverter15Test extends ConverterTestSetup {
deleteProject(jp);
}
}
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=404489
+ public void testBug404489() throws JavaModelException {
+ ICompilationUnit sourceUnit = getCompilationUnit("Converter18" , "src", "test404489.bug", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ ASTNode result = runConversion(this.ast.apiLevel(), sourceUnit, true);
+ assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT);
+ CompilationUnit compilationUnit = (CompilationUnit) result;
+ assertProblemsSize(compilationUnit, 0);
+ ASTNode node = getASTNode(compilationUnit, 0, 0, 0);
+ TypeDeclaration typeDeclaration = (TypeDeclaration) compilationUnit.types().get(0);
+
+ node = (ASTNode) typeDeclaration.bodyDeclarations().get(2);
+ assertEquals("Not a method declaration", ASTNode.METHOD_DECLARATION, node.getNodeType());
+ MethodDeclaration methodDecl = (MethodDeclaration) node;
+ Type type = methodDecl.getReturnType2();
+ assertTrue(type.isQualifiedType());
+ assertTrue(isMalformed(type));
+
+ // parameter
+ SingleVariableDeclaration param = (SingleVariableDeclaration) methodDecl.parameters().get(0);
+ type = param.getType();
+ assertTrue(type.isQualifiedType());
+ assertTrue(isMalformed(type));
+
+ node = (ASTNode) typeDeclaration.bodyDeclarations().get(3);
+ assertEquals("Not a field declaration", ASTNode.FIELD_DECLARATION, node.getNodeType());
+ FieldDeclaration field = (FieldDeclaration) node;
+ type = field.getType();
+ assertTrue(type.isQualifiedType());
+ assertTrue(type.isQualifiedType());
+ assertTrue(isMalformed(type));
+ }
} \ No newline at end of file
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 060867beef..0de56ff3b1 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
@@ -149,10 +149,10 @@ public class ASTConverter18Test extends ConverterTestSetup {
assertNotNull(assignment);
CastExpression castExpression = (CastExpression) assignment.getRightHandSide();
assertNotNull(castExpression);
- SimpleType simpleType = (SimpleType) castExpression.getType();
- assertNotNull(simpleType);
- assertEquals("java.lang.@Marker String", simpleType.toString());
- List annotations = simpleType.annotations();
+ PackageQualifiedType packageQualifiedType = (PackageQualifiedType) castExpression.getType();
+ assertNotNull(packageQualifiedType);
+ assertEquals("java.lang.@Marker String", packageQualifiedType.toString());
+ List annotations = packageQualifiedType.annotations();
assertTrue(annotations.size() == 1);
assertEquals("@Marker", annotations.get(0).toString());
@@ -160,7 +160,7 @@ public class ASTConverter18Test extends ConverterTestSetup {
VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) statements.get(sCount++);
Type type = variableDeclarationStatement.getType();
assertTrue(type.isSimpleType());
- simpleType = (SimpleType) type;
+ SimpleType simpleType = (SimpleType) type;
assertEquals("Outer.Inner", simpleType.toString());
annotations = simpleType.annotations();
assertTrue(annotations.size() == 0);
@@ -169,22 +169,22 @@ public class ASTConverter18Test extends ConverterTestSetup {
// annotations.
variableDeclarationStatement = (VariableDeclarationStatement) statements.get(sCount++);
type = variableDeclarationStatement.getType();
- assertTrue(type.isSimpleType());
- simpleType = (SimpleType) type;
- assertNotNull(simpleType);
- assertEquals("Outer.@Marker2 Inner", simpleType.toString());
- annotations = simpleType.annotations();
+ assertTrue(type.isQualifiedType());
+ QualifiedType qualifiedType = (QualifiedType) type;
+ assertNotNull(qualifiedType);
+ assertEquals("Outer.@Marker2 Inner", qualifiedType.toString());
+ annotations = qualifiedType.annotations();
assertTrue(annotations.size() == 1);
assertEquals("@Marker2", annotations.get(0).toString());
// case 4 - Multiple levels with annotations at the last only.
variableDeclarationStatement = (VariableDeclarationStatement) statements.get(sCount++);
type = variableDeclarationStatement.getType();
- assertTrue(type.isSimpleType());
- simpleType = (SimpleType) type;
- assertNotNull(simpleType);
- assertEquals("Outer.Inner.@Marker1 Deeper", simpleType.toString());
- annotations = simpleType.annotations();
+ assertTrue(type.isQualifiedType());
+ qualifiedType = (QualifiedType) type;
+ assertNotNull(qualifiedType);
+ assertEquals("Outer.Inner.@Marker1 Deeper", qualifiedType.toString());
+ annotations = qualifiedType.annotations();
assertTrue(annotations.size() == 1);
assertEquals("@Marker1", annotations.get(0).toString());
@@ -192,7 +192,7 @@ public class ASTConverter18Test extends ConverterTestSetup {
variableDeclarationStatement = (VariableDeclarationStatement) statements.get(sCount++);
type = variableDeclarationStatement.getType();
assertTrue(type.isQualifiedType());
- QualifiedType qualifiedType = (QualifiedType) type;
+ qualifiedType = (QualifiedType) type;
assertNotNull(qualifiedType);
assertEquals("Outer.@Marker1 Inner.@Marker2 Deeper", qualifiedType.toString());
annotations = qualifiedType.annotations();
@@ -201,10 +201,10 @@ public class ASTConverter18Test extends ConverterTestSetup {
SimpleName simpleName = qualifiedType.getName();
assertEquals("Deeper", simpleName.toString());
Type qualifierType = qualifiedType.getQualifier();
- assertTrue(qualifierType.isSimpleType());
- simpleType = (SimpleType) qualifierType;
- assertEquals("Outer.@Marker1 Inner", simpleType.toString());
- annotations = simpleType.annotations();
+ assertTrue(qualifierType.isQualifiedType());
+ qualifiedType = (QualifiedType) qualifierType;
+ assertEquals("Outer.@Marker1 Inner", qualifiedType.toString());
+ annotations = qualifiedType.annotations();
assertTrue(annotations.size() == 1);
assertEquals("@Marker1", annotations.get(0).toString());
}
@@ -342,10 +342,10 @@ public class ASTConverter18Test extends ConverterTestSetup {
typeArguments = parametrizedType.typeArguments();
assertEquals(1, typeArguments.size());
type = (Type) typeArguments.get(0);
- assertTrue(type.isSimpleType());
- SimpleType simpleType = (SimpleType) type;
- assertEquals("Outer.@Marker1 Inner", simpleType.toString());
- List annotations = simpleType.annotations();
+ assertTrue(type.isQualifiedType());
+ QualifiedType qualifiedType = (QualifiedType) type;
+ assertEquals("Outer.@Marker1 Inner", qualifiedType.toString());
+ List annotations = qualifiedType.annotations();
assertTrue(annotations.size() == 1);
Annotation annotation = (Annotation) annotations.get(0);
assertEquals("@Marker1", annotation.toString());
@@ -359,13 +359,13 @@ public class ASTConverter18Test extends ConverterTestSetup {
type = (Type) typeArguments.get(0);
assertTrue(type.isQualifiedType());
assertEquals("@Marker1 Outer.Inner", type.toString());
- QualifiedType qualifiedType = (QualifiedType) type;
+ qualifiedType = (QualifiedType) type;
assertEquals("Inner", qualifiedType.getName().toString());
annotations = qualifiedType.annotations();
assertTrue(annotations.size() == 0);
Type qualifierType = qualifiedType.getQualifier();
assertTrue(qualifierType.isSimpleType());
- simpleType = (SimpleType) qualifierType;
+ SimpleType simpleType = (SimpleType) qualifierType;
assertEquals("@Marker1 Outer", simpleType.toString());
annotations = simpleType.annotations();
assertTrue(annotations.size() == 1);
@@ -1935,6 +1935,318 @@ public class ASTConverter18Test extends ConverterTestSetup {
method = (MethodDeclaration) type.bodyDeclarations().get(3);
assertEquals("Method should be malformed", ASTNode.MALFORMED, (method.getFlags() & ASTNode.MALFORMED));
}
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=404489
+ public void testBug404489a() throws JavaModelException {
+ String contents =
+ "package test404489.bug;\n" +
+ "public class X { \n" +
+ " class Y { \n" +
+ " class Z {\n" +
+ " public Z(@A X.@B Y Y.this){}\n" +
+ " }\n" +
+ " }\n" +
+ " Object o=(@A X.@B Y.@Marker Z)null;\n" +
+ " }\n" +
+ "@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface Marker {} \n" +
+ "@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface A {} \n" +
+ "@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface B {} \n";
+ this.workingCopy = getWorkingCopy("/Converter18/src/test404489/bug/X.java", true/* resolve */);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ 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 Type Declaration", ASTNode.TYPE_DECLARATION, node.getNodeType());
+ node = (ASTNode) ((TypeDeclaration)node).bodyDeclarations().get(0);
+ assertEquals("Not a Type Declaration", ASTNode.TYPE_DECLARATION, node.getNodeType());
+ node = (ASTNode) ((TypeDeclaration)node).bodyDeclarations().get(0);
+ 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));
+ AnnotatableType annotatableType = method.getReceiverType();
+ assertTrue(annotatableType.isQualifiedType());
+ QualifiedType qualifiedType = (QualifiedType) annotatableType;
+ assertEquals("wrong qualified type", "@A X.@B Y", qualifiedType.toString());
+ ITypeBinding binding = qualifiedType.resolveBinding();
+ assertNotNull("No binding", binding);
+ assertEquals("Wrong qualified name", "test404489.bug.X.Y", binding.getQualifiedName());
+ List annotations = qualifiedType.annotations();
+ assertTrue(annotations.size() == 1);
+ MarkerAnnotation marker = (MarkerAnnotation) annotations.get(0);
+ assertEquals("wrong annotation name", "@B", marker.toString());
+ binding = marker.resolveTypeBinding();
+ assertNotNull("No binding", binding);
+ assertEquals("Wrong qualified name", "test404489.bug.B", binding.getQualifiedName());
+ IAnnotationBinding annotationBinding = marker.resolveAnnotationBinding();
+ assertNotNull(annotationBinding);
+ assertEquals("wrong annotation binding", "B", annotationBinding.getName());
+ Name name = marker.getTypeName();
+ assertTrue(name.isSimpleName());
+ SimpleName simpleName = (SimpleName) name;
+ assertEquals("wrong type name", "B", simpleName.toString());
+ assertEquals("wrong simple name", "B",simpleName.getIdentifier());
+ binding = simpleName.resolveTypeBinding();
+ assertNotNull("No binding", binding);
+ assertEquals("Wrong qualified name", "test404489.bug.B", binding.getQualifiedName());
+ assertTrue(qualifiedType.getQualifier().isSimpleType());
+ SimpleType simpleType = (SimpleType) qualifiedType.getQualifier();
+ assertEquals("incorrect type", "@A X", simpleType.toString());
+ binding = simpleType.resolveBinding();
+ assertNotNull("No binding", binding);
+ assertEquals("Wrong qualified name", "test404489.bug.X.Y", binding.getQualifiedName());
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=404489
+ public void testBug404489b() throws JavaModelException {
+ ICompilationUnit sourceUnit = getCompilationUnit("Converter18" , "src", "test404489.bug", "X.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ ASTNode result = runConversion(this.ast.apiLevel(), sourceUnit, true);
+ char[] source = sourceUnit.getSource().toCharArray();
+ assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT);
+ CompilationUnit compilationUnit = (CompilationUnit) result;
+ assertProblemsSize(compilationUnit, 0);
+ ASTNode node = getASTNode(compilationUnit, 0, 0, 0);
+ TypeDeclaration typeDeclaration = (TypeDeclaration) compilationUnit.types().get(0);
+
+ node = (ASTNode) typeDeclaration.bodyDeclarations().get(2);
+ assertEquals("Not a method declaration", ASTNode.METHOD_DECLARATION, node.getNodeType());
+ MethodDeclaration methodDecl = (MethodDeclaration) node;
+ Type type = methodDecl.getReturnType2();
+ assertTrue(type.isPackageQualifiedType());
+ PackageQualifiedType packageQualifiedType = (PackageQualifiedType) type;
+ checkSourceRange(packageQualifiedType, "test404489.bug.@NonNull IOException", source);
+ ITypeBinding typeBinding = packageQualifiedType.resolveBinding();
+ assertNotNull("null binding", typeBinding);
+ assertEquals("not a valid binding", "test404489.bug.IOException", typeBinding.getQualifiedName());
+
+ // qualifier of the package qualified type
+ Name name = packageQualifiedType.getQualifier();
+ assertTrue(name.isQualifiedName());
+ QualifiedName qualifiedName = (QualifiedName) name;
+ checkSourceRange(qualifiedName, "test404489.bug", source);
+ typeBinding = qualifiedName.resolveTypeBinding();
+ assertNull(typeBinding);
+ IBinding binding = qualifiedName.resolveBinding();
+ assertTrue("not a package binding", binding.getKind() == IBinding.PACKAGE);
+ assertEquals("wrong package binding", "package test404489.bug", binding.toString());
+ name = qualifiedName.getQualifier();
+ assertTrue("wrong name type", name.isSimpleName());
+ SimpleName simpleName = (SimpleName) name;
+ checkSourceRange(simpleName, "test404489", source);
+ typeBinding = simpleName.resolveTypeBinding();
+ assertNull(typeBinding);
+ binding = simpleName.resolveBinding();
+ assertTrue("not a package binding", binding.getKind() == IBinding.PACKAGE);
+ assertEquals("wrong package binding", "package test404489", binding.toString());
+ simpleName = qualifiedName.getName();
+ checkSourceRange(simpleName, "bug", source);
+ typeBinding = simpleName.resolveTypeBinding();
+ assertNull(typeBinding);
+ binding = simpleName.resolveBinding();
+ assertTrue("not a package binding", binding.getKind() == IBinding.PACKAGE);
+ assertEquals("wrong package binding", "package test404489.bug", binding.toString());
+
+ // annotations of package qualified type
+ List annotations = packageQualifiedType.annotations();
+ assertTrue(annotations.size() == 1);
+ Annotation annotation = (Annotation) annotations.get(0);
+ typeBinding = annotation.resolveTypeBinding();
+ assertNotNull("null binding", typeBinding);
+ assertEquals("not a valid binding", "test404489.bug.X.NonNull", typeBinding.getQualifiedName());
+ IAnnotationBinding annotationBinding = annotation.resolveAnnotationBinding();
+ assertEquals("not a valid annotation binding", "@NonNull()", annotationBinding.toString());
+ name = annotation.getTypeName();
+ assertTrue(name.isSimpleName());
+ simpleName = (SimpleName) name;
+ typeBinding = simpleName.resolveTypeBinding();
+ checkSourceRange(simpleName, "NonNull", source);
+ assertNotNull(typeBinding);
+
+ // name of the package qualified type
+ simpleName = packageQualifiedType.getName();
+ checkSourceRange(simpleName, "IOException", source);
+ typeBinding = simpleName.resolveTypeBinding();
+ assertNotNull(typeBinding);
+
+ // parameter
+ SingleVariableDeclaration param = (SingleVariableDeclaration) methodDecl.parameters().get(0);
+ type = param.getType();
+ assertTrue(type.isPackageQualifiedType());
+ packageQualifiedType = (PackageQualifiedType) type;
+ checkSourceRange(packageQualifiedType, "test404489.bug.@NonNull FileNotFoundException", source);
+ typeBinding = packageQualifiedType.resolveBinding();
+ assertNotNull("null binding", typeBinding);
+ assertEquals("not a valid binding", "test404489.bug.FileNotFoundException", typeBinding.getQualifiedName());
+
+ // qualifier of the package qualified type
+ name = packageQualifiedType.getQualifier();
+ assertTrue(name.isQualifiedName());
+ qualifiedName = (QualifiedName) name;
+ checkSourceRange(qualifiedName, "test404489.bug", source);
+ typeBinding = qualifiedName.resolveTypeBinding();
+ assertNull(typeBinding);
+ binding = qualifiedName.resolveBinding();
+ assertTrue("not a package binding", binding.getKind() == IBinding.PACKAGE);
+ assertEquals("wrong package binding", "package test404489.bug", binding.toString());
+ name = qualifiedName.getQualifier();
+ assertTrue("wrong name type", name.isSimpleName());
+ simpleName = (SimpleName) name;
+ checkSourceRange(simpleName, "test404489", source);
+ typeBinding = simpleName.resolveTypeBinding();
+ assertNull(typeBinding);
+ binding = simpleName.resolveBinding();
+ assertTrue("not a package binding", binding.getKind() == IBinding.PACKAGE);
+ assertEquals("wrong package binding", "package test404489", binding.toString());
+ simpleName = qualifiedName.getName();
+ checkSourceRange(simpleName, "bug", source);
+ typeBinding = simpleName.resolveTypeBinding();
+ assertNull(typeBinding);
+ binding = simpleName.resolveBinding();
+ assertTrue("not a package binding", binding.getKind() == IBinding.PACKAGE);
+ assertEquals("wrong package binding", "package test404489.bug", binding.toString());
+
+ // annotations of package qualified type
+ annotations = packageQualifiedType.annotations();
+ assertTrue(annotations.size() == 1);
+ annotation = (Annotation) annotations.get(0);
+ typeBinding = annotation.resolveTypeBinding();
+ assertNotNull("null binding", typeBinding);
+ assertEquals("not a valid binding", "test404489.bug.X.NonNull", typeBinding.getQualifiedName());
+ annotationBinding = annotation.resolveAnnotationBinding();
+ assertEquals("not a valid annotation binding", "@NonNull()", annotationBinding.toString());
+ name = annotation.getTypeName();
+ assertTrue(name.isSimpleName());
+ simpleName = (SimpleName) name;
+ typeBinding = simpleName.resolveTypeBinding();
+ checkSourceRange(simpleName, "NonNull", source);
+ assertNotNull(typeBinding);
+
+ // name of the package qualified type
+ simpleName = packageQualifiedType.getName();
+ checkSourceRange(simpleName, "FileNotFoundException", source);
+ typeBinding = simpleName.resolveTypeBinding();
+ assertNotNull(typeBinding);
+
+ // throws
+ type = (Type) methodDecl.thrownExceptionTypes().get(0);
+ assertTrue(type.isPackageQualifiedType());
+ packageQualifiedType = (PackageQualifiedType) type;
+ checkSourceRange(packageQualifiedType, "test404489.bug.@NonNull EOFException", source);
+ typeBinding = packageQualifiedType.resolveBinding();
+ assertNotNull("null binding", typeBinding);
+ assertEquals("not a valid binding", "test404489.bug.EOFException", typeBinding.getQualifiedName());
+
+ // qualifier of the package qualified type
+ name = packageQualifiedType.getQualifier();
+ assertTrue(name.isQualifiedName());
+ qualifiedName = (QualifiedName) name;
+ checkSourceRange(qualifiedName, "test404489.bug", source);
+ typeBinding = qualifiedName.resolveTypeBinding();
+ assertNull(typeBinding);
+ binding = qualifiedName.resolveBinding();
+ assertTrue("not a package binding", binding.getKind() == IBinding.PACKAGE);
+ assertEquals("wrong package binding", "package test404489.bug", binding.toString());
+ name = qualifiedName.getQualifier();
+ assertTrue("wrong name type", name.isSimpleName());
+ simpleName = (SimpleName) name;
+ checkSourceRange(simpleName, "test404489", source);
+ typeBinding = simpleName.resolveTypeBinding();
+ assertNull(typeBinding);
+ binding = simpleName.resolveBinding();
+ assertTrue("not a package binding", binding.getKind() == IBinding.PACKAGE);
+ assertEquals("wrong package binding", "package test404489", binding.toString());
+ simpleName = qualifiedName.getName();
+ checkSourceRange(simpleName, "bug", source);
+ typeBinding = simpleName.resolveTypeBinding();
+ assertNull(typeBinding);
+ binding = simpleName.resolveBinding();
+ assertTrue("not a package binding", binding.getKind() == IBinding.PACKAGE);
+ assertEquals("wrong package binding", "package test404489.bug", binding.toString());
+
+ // annotations of package qualified type
+ annotations = packageQualifiedType.annotations();
+ assertTrue(annotations.size() == 1);
+ annotation = (Annotation) annotations.get(0);
+ typeBinding = annotation.resolveTypeBinding();
+ assertNotNull("null binding", typeBinding);
+ assertEquals("not a valid binding", "test404489.bug.X.NonNull", typeBinding.getQualifiedName());
+ annotationBinding = annotation.resolveAnnotationBinding();
+ assertEquals("not a valid annotation binding", "@NonNull()", annotationBinding.toString());
+ name = annotation.getTypeName();
+ assertTrue(name.isSimpleName());
+ simpleName = (SimpleName) name;
+ typeBinding = simpleName.resolveTypeBinding();
+ checkSourceRange(simpleName, "NonNull", source);
+ assertNotNull(typeBinding);
+
+ // name of the package qualified type
+ simpleName = packageQualifiedType.getName();
+ checkSourceRange(simpleName, "EOFException", source);
+ typeBinding = simpleName.resolveTypeBinding();
+ assertNotNull(typeBinding);
+
+ node = (ASTNode) typeDeclaration.bodyDeclarations().get(3);
+ assertEquals("Not a field declaration", ASTNode.FIELD_DECLARATION, node.getNodeType());
+ FieldDeclaration field = (FieldDeclaration) node;
+ type = field.getType();
+ assertTrue(type.isQualifiedType());
+ QualifiedType qualifiedType = (QualifiedType) type;
+ packageQualifiedType = (PackageQualifiedType)qualifiedType.getQualifier();
+ checkSourceRange(packageQualifiedType, "test404489.bug.@NonNull X", source);
+ typeBinding = packageQualifiedType.resolveBinding();
+ assertNotNull("null binding", typeBinding);
+ assertEquals("not a valid binding", "test404489.bug.X.Inner", typeBinding.getQualifiedName());
+
+ // qualifier of the package qualified type
+ name = packageQualifiedType.getQualifier();
+ assertTrue(name.isQualifiedName());
+ qualifiedName = (QualifiedName) name;
+ checkSourceRange(qualifiedName, "test404489.bug", source);
+ typeBinding = qualifiedName.resolveTypeBinding();
+ assertNull(typeBinding);
+ binding = qualifiedName.resolveBinding();
+ assertTrue("not a package binding", binding.getKind() == IBinding.PACKAGE);
+ assertEquals("wrong package binding", "package test404489.bug", binding.toString());
+ name = qualifiedName.getQualifier();
+ assertTrue("wrong name type", name.isSimpleName());
+ simpleName = (SimpleName) name;
+ checkSourceRange(simpleName, "test404489", source);
+ typeBinding = simpleName.resolveTypeBinding();
+ assertNull(typeBinding);
+ binding = simpleName.resolveBinding();
+ assertTrue("not a package binding", binding.getKind() == IBinding.PACKAGE);
+ assertEquals("wrong package binding", "package test404489", binding.toString());
+ simpleName = qualifiedName.getName();
+ checkSourceRange(simpleName, "bug", source);
+ typeBinding = simpleName.resolveTypeBinding();
+ assertNull(typeBinding);
+ binding = simpleName.resolveBinding();
+ assertTrue("not a package binding", binding.getKind() == IBinding.PACKAGE);
+ assertEquals("wrong package binding", "package test404489.bug", binding.toString());
+
+ // annotations of package qualified type
+ annotations = packageQualifiedType.annotations();
+ assertTrue(annotations.size() == 1);
+ annotation = (Annotation) annotations.get(0);
+ typeBinding = annotation.resolveTypeBinding();
+ assertNotNull("null binding", typeBinding);
+ assertEquals("not a valid binding", "test404489.bug.X.NonNull", typeBinding.getQualifiedName());
+ annotationBinding = annotation.resolveAnnotationBinding();
+ assertEquals("not a valid annotation binding", "@NonNull()", annotationBinding.toString());
+ name = annotation.getTypeName();
+ assertTrue(name.isSimpleName());
+ simpleName = (SimpleName) name;
+ typeBinding = simpleName.resolveTypeBinding();
+ checkSourceRange(simpleName, "NonNull", source);
+ assertNotNull(typeBinding);
+
+ // name of the package qualified type
+ simpleName = packageQualifiedType.getName();
+ checkSourceRange(simpleName, "X", source);
+ typeBinding = simpleName.resolveTypeBinding();
+ assertNotNull(typeBinding);
+
+ }
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=399792
public void testBug399792() throws JavaModelException {
String content =
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTMatcherTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTMatcherTest.java
index 970ef6ecd9..4ec77591d4 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTMatcherTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTMatcherTest.java
@@ -453,6 +453,9 @@ public class ASTMatcherTest extends org.eclipse.jdt.core.tests.junit.extension.T
public boolean match(PackageDeclaration node, Object other) {
return standardBody(node, other, this.superMatch ? super.match(node, other) : false);
}
+ public boolean match(PackageQualifiedType node, Object other) {
+ return standardBody(node, other, this.superMatch ? super.match(node, other) : false);
+ }
public boolean match(ParameterizedType node, Object other) {
return standardBody(node, other, this.superMatch ? super.match(node, other) : false);
}
@@ -708,6 +711,15 @@ public class ASTMatcherTest extends org.eclipse.jdt.core.tests.junit.extension.T
}
/** @deprecated using deprecated code */
+ public void testPackageQualifiedType() {
+ if (this.ast.apiLevel() < AST.JLS8) {
+ return;
+ }
+ Type x1 = this.ast.newPackageQualifiedType(this.ast.newQualifiedName(this.N2, this.N3), this.N1);
+ basicMatch(x1);
+ }
+
+ /** @deprecated using deprecated code */
public void testParameterizedType() {
if (this.ast.apiLevel() == AST.JLS2) {
return;
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java
index b000cb7711..c236a0b2d5 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java
@@ -328,7 +328,7 @@ public class ASTStructuralPropertyTest extends org.eclipse.jdt.core.tests.junit.
maxNodeType = 84;
break;
case AST.JLS8:
- maxNodeType = 87;
+ maxNodeType = 88;
break;
default:
fail();
@@ -372,7 +372,7 @@ public class ASTStructuralPropertyTest extends org.eclipse.jdt.core.tests.junit.
// oops - guess that's not valid
}
}
- assertEquals("Wrong last known type", 87, hi); // last known one
+ assertEquals("Wrong last known type", 88, hi); // last known one
assertEquals("Wrong number of distinct types", hi, classes.size()); // all classes are distinct
}
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java
index 4333a8fefc..52c8dd2924 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java
@@ -8784,6 +8784,7 @@ public class ASTTest extends org.eclipse.jdt.core.tests.junit.extension.TestCase
ASTNode.EXTRA_DIMENSION,
ASTNode.LAMBDA_EXPRESSION,
ASTNode.INTERSECTION_TYPE,
+ ASTNode.PACKAGE_QUALIFIED_TYPE,
};
// assert that nodeType values are correct:
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java
index 0072ed8c51..ff0db3a211 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java
@@ -383,6 +383,13 @@ public class ASTVisitorTest extends org.eclipse.jdt.core.tests.junit.extension.T
ASTVisitorTest.this.b.append(node.getPrimitiveTypeCode().toString());
ASTVisitorTest.this.b.append("tP)"); //$NON-NLS-1$
}
+ public boolean visit(PackageQualifiedType node) {
+ ASTVisitorTest.this.b.append("(tPQ"); //$NON-NLS-1$
+ return isVisitingChildren();
+ }
+ public void endVisit(PackageQualifiedType node) {
+ ASTVisitorTest.this.b.append("tPQ)"); //$NON-NLS-1$
+ }
public boolean visit(ParameterizedType node) {
ASTVisitorTest.this.b.append("(tM"); //$NON-NLS-1$
return isVisitingChildren();
@@ -1122,6 +1129,20 @@ public class ASTVisitorTest extends org.eclipse.jdt.core.tests.junit.extension.T
}
/** @deprecated using deprecated code */
+ public void testPackageQualifiedType() {
+ if (this.ast.apiLevel() < AST.JLS8) {
+ return;
+ }
+ QualifiedName q = this.ast.newQualifiedName(this.N2, this.N3);
+ PackageQualifiedType x1 = this.ast.newPackageQualifiedType(q, this.N1);
+ TestVisitor v1 = new TestVisitor();
+ this.b.setLength(0);
+ x1.accept(v1);
+ String result = this.b.toString();
+ assertTrue(result.equals("[(tPQ"+"[(nQ"+this.N2S+this.N3S+"nQ)]"+this.N1S+"tPQ)]")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /** @deprecated using deprecated code */
public void testParameterizedType() {
if (this.ast.apiLevel() == AST.JLS2) {
return;
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Converter15/src/test404489/bug/X.java b/org.eclipse.jdt.core.tests.model/workspace/Converter15/src/test404489/bug/X.java
new file mode 100644
index 0000000000..4cf542aa4c
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Converter15/src/test404489/bug/X.java
@@ -0,0 +1,37 @@
+package test404489.bug;
+import java.lang.annotation.*;
+public class X {
+ @Target(ElementType.TYPE_USE)
+ @Retention(RetentionPolicy.RUNTIME)
+ @Documented
+ static @interface NonNull { }
+ class Inner {}
+
+ /**
+ * @param arg
+ */
+ test404489.bug.@NonNull IOException foo(
+ test404489.bug.@NonNull FileNotFoundException arg)
+ throws test404489.bug.@NonNull EOFException {
+ try {
+ test404489.bug.@NonNull IOError e = new test404489.bug.IOError();
+ throw e;
+ } catch (test404489.bug.@NonNull IOError e) {
+ }
+ return null;
+ }
+ test404489.bug.@NonNull X.@NonNull Inner fInner;
+}
+@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface Marker {}
+@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface A {}
+@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface B {}
+
+class Outer {
+ public class Inner {
+ public class Deeper {}
+ }
+}
+class IOException extends Exception {private static final long serialVersionUID=10001L;}
+class FileNotFoundException extends Exception{private static final long serialVersionUID=10002L;}
+class EOFException extends Exception{private static final long serialVersionUID=10003L;}
+class IOError extends Exception{private static final long serialVersionUID=10004L;} \ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.model/workspace/Converter18/src/test404489/bug/X.java b/org.eclipse.jdt.core.tests.model/workspace/Converter18/src/test404489/bug/X.java
new file mode 100644
index 0000000000..4cf542aa4c
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/Converter18/src/test404489/bug/X.java
@@ -0,0 +1,37 @@
+package test404489.bug;
+import java.lang.annotation.*;
+public class X {
+ @Target(ElementType.TYPE_USE)
+ @Retention(RetentionPolicy.RUNTIME)
+ @Documented
+ static @interface NonNull { }
+ class Inner {}
+
+ /**
+ * @param arg
+ */
+ test404489.bug.@NonNull IOException foo(
+ test404489.bug.@NonNull FileNotFoundException arg)
+ throws test404489.bug.@NonNull EOFException {
+ try {
+ test404489.bug.@NonNull IOError e = new test404489.bug.IOError();
+ throw e;
+ } catch (test404489.bug.@NonNull IOError e) {
+ }
+ return null;
+ }
+ test404489.bug.@NonNull X.@NonNull Inner fInner;
+}
+@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface Marker {}
+@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface A {}
+@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface B {}
+
+class Outer {
+ public class Inner {
+ public class Deeper {}
+ }
+}
+class IOException extends Exception {private static final long serialVersionUID=10001L;}
+class FileNotFoundException extends Exception{private static final long serialVersionUID=10002L;}
+class EOFException extends Exception{private static final long serialVersionUID=10003L;}
+class IOError extends Exception{private static final long serialVersionUID=10004L;} \ No newline at end of file
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
index 4ec76ca0c7..20781c3d80 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java
@@ -1971,6 +1971,29 @@ public final class AST {
}
/**
+ * Creates and returns a new unparented package qualified type node with
+ * the given qualifier and name.
+ *
+ * @param qualifier the package qualifier type node
+ * @param name the simple name being qualified
+ * @return a new unparented qualified type node
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ * @exception UnsupportedOperationException if this operation is used in
+ * a JLS2, JLS3 and JLS4 AST
+ * @since 3.9 BETA_JAVA8
+ */
+ public PackageQualifiedType newPackageQualifiedType(Name qualifier, SimpleName name) {
+ PackageQualifiedType result = new PackageQualifiedType(this);
+ result.setQualifier(qualifier);
+ result.setName(name);
+ return result;
+ }
+
+ /**
* Creates and returns a new unparented parameterized type node with the
* given type and an empty list of type arguments.
*
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
index 43a6c338ad..151e91e4b6 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
@@ -17,6 +17,7 @@
package org.eclipse.jdt.core.dom;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -57,6 +58,8 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.parser.RecoveryScanner;
import org.eclipse.jdt.internal.compiler.parser.Scanner;
@@ -3296,9 +3299,6 @@ class ASTConverter {
org.eclipse.jdt.internal.compiler.ast.Annotation typeAnnotation = annotations[i];
if (typeAnnotation != null) {
Annotation annotation = convert(typeAnnotation);
- int start = typeAnnotation.sourceStart;
- int end = typeAnnotation.sourceEnd;
- annotation.setSourceRange(start, end - start + 1);
type.annotations().add(annotation);
}
}
@@ -3329,9 +3329,6 @@ class ASTConverter {
org.eclipse.jdt.internal.compiler.ast.Annotation typeAnnotation = annotations[i];
if (typeAnnotation != null) {
Annotation annotation = convert(typeAnnotation);
- int start = typeAnnotation.sourceStart;
- int end = typeAnnotation.sourceEnd;
- annotation.setSourceRange(start, end - start + 1);
typeParameter.annotations().add(annotation);
}
}
@@ -3546,13 +3543,7 @@ class ASTConverter {
simpleType.setName(name);
int start = (int)(positions[0] >>> 32);
int end = (int)positions[firstTypeIndex];
- simpleType.setSourceRange(start, end - start + 1);
- if (typeAnnotations != null && (annotations = typeAnnotations[firstTypeIndex]) != null) {
- annotateType(simpleType, annotations);
- }
- if (this.resolveBindings) {
- recordNodes(simpleType, typeReference);
- }
+ setSourceRangeAnnotationsAndRecordNodes(typeReference, simpleType, positions, typeAnnotations, firstTypeIndex, 0, firstTypeIndex);
Type currentType = simpleType;
int indexOfEnclosingType = 1;
if (typeArguments != null && (arguments = typeArguments[firstTypeIndex]) != null) {
@@ -3628,7 +3619,7 @@ class ASTConverter {
org.eclipse.jdt.internal.compiler.ast.Annotation [][] typeAnnotations = typeReference.annotations;
char [][] tokens = qualifiedTypeReference.tokens;
int lenth = tokens.length;
- int firstTypeIndex = lenth - 1;
+ int firstTypeIndex = lenth;
if (typeAnnotations != null) {
for (int i = 0; i < lenth; ++i) {
@@ -3640,57 +3631,44 @@ class ASTConverter {
}
sourceStart = (int)(positions[0]>>>32);
Name name = null;
- if (firstTypeIndex == 0) {
- final SimpleName simpleName = new SimpleName(this.ast);
- simpleName.internalSetIdentifier(new String(tokens[0]));
- recordPendingNameScopeResolution(simpleName);
- int start = (int) (positions[0] >>> 32);
- int end = (int) positions[0];
- simpleName.setSourceRange(start, end);
- simpleName.index = 1;
- name = simpleName;
- if (this.resolveBindings) {
- recordNodes(simpleName, typeReference);
- }
+ Type currentType = null;
+ if (firstTypeIndex == lenth) {//Just a QualifiedName
+ name = setQualifiedNameNameAndSourceRanges(tokens, positions, lenth - 1, typeReference);
+ currentType = createSimpleType(name, typeReference, positions, 0, lenth - 1);
} else {
- name = setQualifiedNameNameAndSourceRanges(tokens, positions, firstTypeIndex, typeReference);
- }
- SimpleType simpleType = new SimpleType(this.ast);
- simpleType.setName(name);
- int start = (int)(positions[0] >>> 32);
- int end = (int)positions[firstTypeIndex];
- simpleType.setSourceRange(start, end - start + 1);
- if (typeAnnotations != null && (annotations = typeAnnotations[firstTypeIndex]) != null) {
- annotateType(simpleType, annotations);
- }
- if (this.resolveBindings) {
- recordNodes(simpleType, typeReference);
- }
- Type currentType = simpleType;
-
- for (int i = firstTypeIndex + 1; i < lenth; ++i) {
- SimpleName simpleName = new SimpleName(this.ast);
- simpleName.internalSetIdentifier(new String(tokens[i]));
- simpleName.index = i + 1;
- start = (int) (positions[i] >>> 32);
- end = (int) positions[i];
- simpleName.setSourceRange(start, end - start +1);
- recordPendingNameScopeResolution(simpleName);
- QualifiedType qualifiedType = new QualifiedType(this.ast);
- qualifiedType.setQualifier(currentType);
- qualifiedType.setName(simpleName);
- if (typeAnnotations != null && (annotations = typeAnnotations[i]) != null) {
- annotateType(qualifiedType, annotations);
+ if (firstTypeIndex <= 1) {
+ name = createSimpleName(typeReference, positions, tokens, 0 );
+ firstTypeIndex = 1;
+ } else {
+ name = setQualifiedNameNameAndSourceRanges(tokens, positions, firstTypeIndex - 1, typeReference);
+ }
+
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding typeBinding = typeReference.resolvedType;
+ boolean createPackageQualifiedType = false;
+ if (typeBinding instanceof ReferenceBinding) {
+ ReferenceBinding referenceBinding = (ReferenceBinding)typeBinding;
+ PackageBinding packageBinding = referenceBinding.getPackage();
+ if (packageBinding != null && Arrays.equals(name.toString().toCharArray(), packageBinding.readableName())) {
+ createPackageQualifiedType = true;
+ }
}
- if (this.resolveBindings) {
- recordNodes(simpleName, typeReference);
- recordNodes(qualifiedType, typeReference);
+
+ if (createPackageQualifiedType && this.ast.apiLevel >= AST.JLS8) {
+ PackageQualifiedType packageQualifiedType = new PackageQualifiedType(this.ast);
+ packageQualifiedType.setQualifier(name);
+ packageQualifiedType.setName(createSimpleName(typeReference, positions, tokens, firstTypeIndex));
+ setSourceRangeAnnotationsAndRecordNodes(typeReference, packageQualifiedType, positions, typeAnnotations, firstTypeIndex, 0, firstTypeIndex);
+ currentType = packageQualifiedType;
+ } else {
+ SimpleType simpleType = this.ast.newSimpleType(name);
+ setSourceRangeAnnotationsAndRecordNodes(typeReference, simpleType, positions, typeAnnotations, 0, 0, name.index > 0 ? name.index - 1 : 0);
+ currentType = createQualifiedType(typeReference, positions, typeAnnotations, tokens, firstTypeIndex, simpleType);
+ if (createPackageQualifiedType)
+ currentType.setFlags(currentType.getFlags() | ASTNode.MALFORMED);
}
- start = currentType.getStartPosition();
- end = simpleName.getStartPosition() + simpleName.getLength() - 1;
- qualifiedType.setSourceRange(start, end - start + 1);
- currentType = qualifiedType;
- qualifiedType.index = 1;
+ for (int i = firstTypeIndex + 1; i < lenth; ++i) {
+ currentType = createQualifiedType(typeReference, positions, typeAnnotations, tokens, i, currentType);
+ }
}
type = currentType;
} else if (typeReference instanceof UnionTypeReference){
@@ -3808,6 +3786,71 @@ class ASTConverter {
return type;
}
+ private QualifiedType createQualifiedType(TypeReference typeReference, long[] positions,
+ org.eclipse.jdt.internal.compiler.ast.Annotation[][] typeAnnotations, char[][] tokens, int index,
+ Type qualifier) {
+ SimpleName simpleName = createSimpleName(typeReference, positions, tokens, index);
+ QualifiedType qualifiedType = new QualifiedType(this.ast);
+ qualifiedType.setQualifier(qualifier);
+ qualifiedType.setName(simpleName);
+ int start = qualifier.getStartPosition();
+ int end = simpleName.getStartPosition() + simpleName.getLength() - 1;
+ setSourceRangeAnnotationsAndRecordNodes(typeReference, qualifiedType, typeAnnotations, index, start, end);
+ return qualifiedType;
+ }
+
+ private SimpleType createSimpleType(Name name, TypeReference typeReference, long[] positions,
+ int startIndex, int endIndex) {
+ SimpleType simpleType = new SimpleType(this.ast);
+ simpleType.setName(name);
+ int start = (int)(positions[startIndex] >>> 32);
+ int end = (int)positions[endIndex];
+ simpleType.setSourceRange(start, end - start + 1);
+ if (this.resolveBindings) {
+ recordNodes(simpleType, typeReference);
+ }
+ return simpleType;
+ }
+
+ private void setSourceRangeAnnotationsAndRecordNodes(TypeReference typeReference, AnnotatableType annotatableType,
+ org.eclipse.jdt.internal.compiler.ast.Annotation[][] typeAnnotations, int index, int start, int end) {
+ org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations;
+ int annotationsStart = start;
+ int length = end - start + 1;
+ if (typeAnnotations != null && (annotations = typeAnnotations[index]) != null) {
+ annotateType(annotatableType, annotations);
+ if (annotations[0] != null && (annotationsStart = annotations[0].sourceStart) < start) {
+ length += annotationsStart > 0 ? start - annotationsStart : 0;
+ start = annotationsStart;
+ }
+ }
+ annotatableType.setSourceRange(start, length);
+ if (this.resolveBindings) {
+ recordNodes(annotatableType, typeReference);
+ }
+ }
+
+ private void setSourceRangeAnnotationsAndRecordNodes(TypeReference typeReference, AnnotatableType annotatableType,
+ long[] positions, org.eclipse.jdt.internal.compiler.ast.Annotation[][] typeAnnotations, int index, int startIndex, int endIndex) {
+ int start = (int) (positions[startIndex] >>> 32);
+ int end = (int) positions[endIndex];
+ setSourceRangeAnnotationsAndRecordNodes(typeReference, annotatableType, typeAnnotations, index, start, end);
+ }
+
+ private SimpleName createSimpleName(TypeReference typeReference, long[] positions, char[][] tokens, int index) {
+ final SimpleName simpleName = new SimpleName(this.ast);
+ simpleName.internalSetIdentifier(new String(tokens[index]));
+ recordPendingNameScopeResolution(simpleName);
+ int start = (int) (positions[index] >>> 32);
+ int end = (int) positions[index];
+ simpleName.setSourceRange(start, end - start + 1);
+ simpleName.index = index + 1;
+ if (this.resolveBindings) {
+ recordNodes(simpleName, typeReference);
+ }
+ return simpleName;
+ }
+
protected Comment createComment(int[] positions) {
// Create comment node
Comment comment = null;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
index 4e816602dd..d631372d55 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java
@@ -1592,6 +1592,31 @@ public class ASTMatcher {
* @return <code>true</code> if the subtree matches, or
* <code>false</code> if they do not match or the other object has a
* different node type or is <code>null</code>
+ * @since 3.9 BETA_JAVA8
+ */
+ public boolean match(PackageQualifiedType node, Object other) {
+ if (!(other instanceof PackageQualifiedType)) {
+ return false;
+ }
+ PackageQualifiedType o = (PackageQualifiedType) other;
+ return safeSubtreeMatch(node.getQualifier(), o.getQualifier())
+ && safeSubtreeListMatch(node.annotations(), o.annotations())
+ && safeSubtreeMatch(node.getName(), o.getName());
+ }
+
+ /**
+ * Returns whether the given node and the other object match.
+ * <p>
+ * The default implementation provided by this class tests whether the
+ * other object is a node of the same type with structurally isomorphic
+ * child subtrees. Subclasses may override this method as needed.
+ * </p>
+ *
+ * @param node the node
+ * @param other the other object, or <code>null</code>
+ * @return <code>true</code> if the subtree matches, or
+ * <code>false</code> if they do not match or the other object has a
+ * different node type or is <code>null</code>
* @since 3.1
*/
public boolean match(ParameterizedType node, Object other) {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
index 3ebd6ffca3..2a87561f86 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTNode.java
@@ -860,6 +860,14 @@ public abstract class ASTNode {
public static final int INTERSECTION_TYPE = 87;
/**
+ * Node type constant indicating a node of type
+ * <code>QualifiedType</code>.
+ * @see QualifiedType
+ * @since 3.9 BETA_JAV8
+ */
+ public static final int PACKAGE_QUALIFIED_TYPE = 88;
+
+ /**
* Returns the node class for the corresponding node type.
*
* @param nodeType AST node type
@@ -979,6 +987,8 @@ public abstract class ASTNode {
return NumberLiteral.class;
case PACKAGE_DECLARATION :
return PackageDeclaration.class;
+ case PACKAGE_QUALIFIED_TYPE :
+ return PackageQualifiedType.class;
case PARAMETERIZED_TYPE :
return ParameterizedType.class;
case PARENTHESIZED_EXPRESSION :
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
index fe08581e21..d519f2a63a 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTVisitor.java
@@ -1089,6 +1089,23 @@ public abstract class ASTVisitor {
* @return <code>true</code> if the children of this node should be
* visited, and <code>false</code> if the children of this node should
* be skipped
+ * @since 3.9 BETA_JAVA8
+ */
+ public boolean visit(PackageQualifiedType node) {
+ return true;
+ }
+
+ /**
+ * Visits the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing and return true.
+ * Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
+ * @return <code>true</code> if the children of this node should be
+ * visited, and <code>false</code> if the children of this node should
+ * be skipped
* @since 3.1
*/
public boolean visit(ParameterizedType node) {
@@ -2291,6 +2308,19 @@ public abstract class ASTVisitor {
* </p>
*
* @param node the node to visit
+ * @since 3.9 BETA_JAVA8
+ */
+ public void endVisit(PackageQualifiedType node) {
+ // default implementation: do nothing
+ }
+
+ /**
+ * End of visit the given type-specific AST node.
+ * <p>
+ * The default implementation does nothing. Subclasses may reimplement.
+ * </p>
+ *
+ * @param node the node to visit
* @since 3.1
*/
public void endVisit(ParameterizedType node) {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java
index a6ef4417d6..51f2bf49cf 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultASTVisitor.java
@@ -188,6 +188,9 @@ class DefaultASTVisitor extends ASTVisitor {
public void endVisit(PackageDeclaration node) {
endVisitNode(node);
}
+ public void endVisit(PackageQualifiedType node) {
+ endVisitNode(node);
+ }
public void endVisit(ParameterizedType node) {
endVisitNode(node);
}
@@ -460,6 +463,9 @@ class DefaultASTVisitor extends ASTVisitor {
public boolean visit(PackageDeclaration node) {
return visitNode(node);
}
+ public boolean visit(PackageQualifiedType node) {
+ return visitNode(node);
+ }
public boolean visit(ParameterizedType node) {
return visitNode(node);
}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageQualifiedType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageQualifiedType.java
new file mode 100644
index 0000000000..173053d168
--- /dev/null
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/PackageQualifiedType.java
@@ -0,0 +1,285 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2013 IBM Corporation 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
+ *
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.core.dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Node for a package qualified type (added in JLS8 API).
+ *
+ * <pre>
+ * PackageQualifiedType:
+ * Name <b>.</b> { Annotation } SimpleName
+ * </pre>
+ *
+ * @since 3.9 BETA_JAVA8
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class PackageQualifiedType extends AnnotatableType {
+
+ /**
+ * The "qualifier" structural property of this node type (child type: {@link Name}).
+ */
+ public static final ChildPropertyDescriptor QUALIFIER_PROPERTY =
+ new ChildPropertyDescriptor(PackageQualifiedType.class, "qualifier", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * The "annotations" structural property of this node type (element type: {@link Annotation}).
+ */
+ public static final ChildListPropertyDescriptor ANNOTATIONS_PROPERTY =
+ internalAnnotationsPropertyFactory(PackageQualifiedType.class);
+
+ /**
+ * The "name" structural property of this node type (child type: {@link SimpleName}).
+ */
+ public static final ChildPropertyDescriptor NAME_PROPERTY =
+ new ChildPropertyDescriptor(PackageQualifiedType.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
+
+ /**
+ * A list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor}),
+ * or null if uninitialized.
+ */
+ private static final List PROPERTY_DESCRIPTORS;
+
+ static {
+ List propertyList = new ArrayList(4);
+ createPropertyList(PackageQualifiedType.class, propertyList);
+ addProperty(QUALIFIER_PROPERTY, propertyList);
+ addProperty(ANNOTATIONS_PROPERTY, propertyList);
+ addProperty(NAME_PROPERTY, propertyList);
+ PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
+ }
+
+ /**
+ * Returns a list of structural property descriptors for this node type.
+ * Clients must not modify the result.
+ *
+ * @param apiLevel the API level; one of the
+ * <code>AST.JLS*</code> constants
+ * @return a list of property descriptors (element type:
+ * {@link StructuralPropertyDescriptor})
+ */
+ public static List propertyDescriptors(int apiLevel) {
+ return PROPERTY_DESCRIPTORS;
+ }
+
+ /**
+ * The qualifier node; lazily initialized; defaults to
+ * an unspecified, but legal, simple name.
+ */
+ private Name qualifier = null;
+
+ /**
+ * The name being qualified; lazily initialized; defaults to a unspecified,
+ * legal Java identifier.
+ */
+ private SimpleName name = null;
+
+ /**
+ * Creates a new unparented node for a package qualified type owned by the
+ * given AST. By default, an unspecified, but legal, qualifier and name.
+ * <p>
+ * N.B. This constructor is package-private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ */
+ PackageQualifiedType(AST ast) {
+ super(ast);
+ unsupportedIn2_3_4();
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on AnnotatableType.
+ */
+ ChildListPropertyDescriptor internalAnnotationsProperty() {
+ return ANNOTATIONS_PROPERTY;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ List internalStructuralPropertiesForType(int apiLevel) {
+ return propertyDescriptors(apiLevel);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
+ if (property == ANNOTATIONS_PROPERTY) {
+ return annotations();
+ }
+ // allow default implementation to flag the error
+ return super.internalGetChildListProperty(property);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
+ if (property == QUALIFIER_PROPERTY) {
+ if (get) {
+ return getQualifier();
+ } else {
+ setQualifier((Name) child);
+ return null;
+ }
+ }
+ if (property == NAME_PROPERTY) {
+ if (get) {
+ return getName();
+ } else {
+ setName((SimpleName) child);
+ return null;
+ }
+ }
+ // allow default implementation to flag the error
+ return super.internalGetSetChildProperty(property, get, child);
+ }
+
+ int getNodeType0() {
+ return PACKAGE_QUALIFIED_TYPE;
+ }
+
+ boolean subtreeMatch0(ASTMatcher matcher, Object other) {
+ // dispatch to correct overloaded match method
+ return matcher.match(this, other);
+ }
+
+ ASTNode clone0(AST target) {
+ PackageQualifiedType result = new PackageQualifiedType(target);
+ result.setSourceRange(getStartPosition(), getLength());
+ result.setQualifier((Name) ((ASTNode) getQualifier()).clone(target));
+ result.annotations().addAll(ASTNode.copySubtrees(target, annotations()));
+ result.setName((SimpleName) ((ASTNode) getName()).clone(target));
+ return result;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ void accept0(ASTVisitor visitor) {
+ boolean visitChildren = visitor.visit(this);
+ if (visitChildren) {
+ // visit children in normal left to right reading order
+ acceptChild(visitor, getQualifier());
+ acceptChildren(visitor, this.annotations);
+ acceptChild(visitor, getName());
+ }
+ visitor.endVisit(this);
+ }
+
+ /**
+ * Returns the qualifier of this package qualified type.
+ *
+ * @return the qualifier of this package qualified type
+ */
+ public Name getQualifier() {
+ if (this.qualifier == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.qualifier == null) {
+ preLazyInit();
+ this.qualifier = new SimpleName(this.ast);
+ postLazyInit(this.qualifier, QUALIFIER_PROPERTY);
+ }
+ }
+ }
+ return this.qualifier;
+ }
+
+ /**
+ * Sets the qualifier of this package qualified type to the given name.
+ *
+ * @param name the new qualifier of this package qualified type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setQualifier(Name name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.qualifier;
+ preReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ this.qualifier = name;
+ postReplaceChild(oldChild, name, QUALIFIER_PROPERTY);
+ }
+
+ /**
+ * Returns the name part of this package qualified type.
+ *
+ * @return the name being qualified
+ */
+ public SimpleName getName() {
+ if (this.name == null) {
+ // lazy init must be thread-safe for readers
+ synchronized (this) {
+ if (this.name == null) {
+ preLazyInit();
+ this.name = new SimpleName(this.ast);
+ postLazyInit(this.name, NAME_PROPERTY);
+ }
+ }
+ }
+ return this.name;
+ }
+
+ /**
+ * Sets the name part of this package qualified type to the given simple name.
+ *
+ * @param name the identifier of this qualified name
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * </ul>
+ */
+ public void setName(SimpleName name) {
+ if (name == null) {
+ throw new IllegalArgumentException();
+ }
+ ASTNode oldChild = this.name;
+ preReplaceChild(oldChild, name, NAME_PROPERTY);
+ this.name = name;
+ postReplaceChild(oldChild, name, NAME_PROPERTY);
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int memSize() {
+ // treat Code as free
+ return BASE_NODE_SIZE + 2 * 4;
+ }
+
+ /* (omit javadoc for this method)
+ * Method declared on ASTNode.
+ */
+ int treeSize() {
+ return
+ memSize()
+ + (this.qualifier == null ? 0 : getQualifier().treeSize())
+ + (this.annotations == null ? 0 : this.annotations.listSize())
+ + (this.name == null ? 0 : getName().treeSize());
+ }
+
+}
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 f0e8b40ef1..b72d128d91 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
@@ -1,10 +1,14 @@
/*******************************************************************************
- * Copyright (c) 2007, 2011 IBM Corporation and others.
+ * Copyright (c) 2007, 2013 IBM Corporation 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
*
+ * This is an implementation of an early-draft specification developed under the Java
+ * Community Process (JCP) and is made available for testing and evaluation purposes
+ * only. The code is not compatible with any specification of the JCP.
+ *
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
@@ -663,6 +667,9 @@ class RecoveredTypeBinding implements ITypeBinding {
case ASTNode.QUALIFIED_TYPE :
QualifiedType qualifiedType = (QualifiedType) type;
return qualifiedType.getName().getIdentifier();
+ case ASTNode.PACKAGE_QUALIFIED_TYPE :
+ PackageQualifiedType packageQualifiedType = (PackageQualifiedType) type;
+ return packageQualifiedType.getName().getIdentifier();
case ASTNode.SIMPLE_TYPE :
SimpleType simpleType = (SimpleType) type;
Name name = simpleType.getName();
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Type.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Type.java
index 4d7ff0b61c..8b4e9bcf00 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Type.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/Type.java
@@ -33,6 +33,7 @@ package org.eclipse.jdt.core.dom;
* ArrayType
* SimpleType
* QualifiedType
+ * PackageQualifiedType
* WildcardType
* ParameterizedType
* UnionType
@@ -54,6 +55,8 @@ package org.eclipse.jdt.core.dom;
* { Annotation } TypeName
* {@link QualifiedType}:
* Type <b>.</b> {Annotation} SimpleName
+ * {@link PackageQualifiedType}:
+ * Name <b>.</b> { Annotation } SimpleName
* {@link WildcardType}:
* { Annotation } <b>?</b> [ ( <b>extends</b> | <b>super</b>) Type ]
* {@link ParameterizedType}:
@@ -115,6 +118,18 @@ public abstract class Type extends ASTNode {
}
/**
+ * Returns whether this type is a package qualified type
+ * ({@link PackageQualifiedType}).
+ *
+ * @return <code>true</code> if this is a package qualified type, and
+ * <code>false</code> otherwise
+ * @since 3.9 BETA_JAVA8
+ */
+ public final boolean isPackageQualifiedType() {
+ return (this instanceof PackageQualifiedType);
+ }
+
+ /**
* Returns whether this type is a parameterized type
* ({@link ParameterizedType}).
*
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java
index a9c1d606c2..27fdab7c9f 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java
@@ -1202,6 +1202,18 @@ public class NaiveASTFlattener extends ASTVisitor {
}
/*
+ * @see ASTVisitor#visit(PackageQualifiedType)
+ * @since 3.9 BETA_JAVA8
+ */
+ public boolean visit(PackageQualifiedType node) {
+ node.getQualifier().accept(this);
+ this.buffer.append('.');
+ visitTypeAnnotations(node);
+ node.getName().accept(this);
+ return false;
+ }
+
+ /*
* @see ASTVisitor#visit(ParameterizedType)
* @since 3.1
*/

Back to the top