diff options
| author | Manoj Palat | 2013-04-23 05:35:41 +0000 |
|---|---|---|
| committer | Jayaprakash Arthanareeswaran | 2013-04-23 05:35:41 +0000 |
| commit | d3d92e370789aaaed8a46c804d74e3cb2b4bb167 (patch) | |
| tree | a14f4b0e3a0f327dc11f3030aa50ee313ad051c9 | |
| parent | e6029c8b1adfe1296ee554ed42f00e5a663cecbf (diff) | |
| download | eclipse.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
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 */ |
