Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2014-01-01 23:10:41 +0000
committerStephan Herrmann2014-01-01 23:10:41 +0000
commit5d5b2c392efc46f80b4757eb5358cde356fe97c1 (patch)
tree9ca6a3320d559487d880bdfcc87bb05fbca528c9
parent8ac7131a169ac51fd2a2a989a5128b7bc9e2213b (diff)
downloadorg.eclipse.objectteams-5d5b2c392efc46f80b4757eb5358cde356fe97c1.tar.gz
org.eclipse.objectteams-5d5b2c392efc46f80b4757eb5358cde356fe97c1.tar.xz
org.eclipse.objectteams-5d5b2c392efc46f80b4757eb5358cde356fe97c1.zip
update jdt.core from origin BETA_JAVA8 with
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TypeAnnotationSyntaxTest.java29
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java12
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java19
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java3
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java25
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest8.java7
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GrammarCoverageTests308.java3
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeTypeAnnotationTest.java658
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java280
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java774
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RepeatableAnnotationTest.java840
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java5
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java512
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava8Tests.java2
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS4Test.java31
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS8Test.java26
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15Test.java27
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter18Test.java679
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java17
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java17
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java36
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocFlattener.java24
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java17
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest2.java35
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java37
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST4_2.java37
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST8_2.java136
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTStructuralPropertyTest.java2
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTTest.java108
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTVisitorTest.java6
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeAnnotationsConverterTest.java12
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java1627
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java13
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingExpressionsTest.java16
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingMethodDeclTest.java18
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingReferenceExpressionTest.java27
-rw-r--r--org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingStatementsTest.java109
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java8
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java8
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java33
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java6
-rw-r--r--org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java17
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java70
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java12
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java149
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java10
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java935
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java52
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java41
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java15
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java16
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java17
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntersectionCastTypeReference.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocImplicitTypeReference.java8
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java12
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java1
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java30
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java48
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java55
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java53
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java37
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java15
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java21
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java11
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java106
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnionTypeReference.java13
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java23
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationContext.java19
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java3
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/MultiCatchExceptionLabel.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/TypeAnnotationCodeStream.java19
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java15
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java150
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java10
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java11
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java17
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java199
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java71
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java56
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java30
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java21
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java25
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java182
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java36
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MissingTypeBinding.java19
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java20
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java13
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java38
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java24
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java39
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java60
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java328
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java6
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java39
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java80
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java92
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnannotatedTypeSystem.java45
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedAnnotationBinding.java11
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java18
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java29
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java192
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java12
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java106
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties17
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfType.java25
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/LiftingTypeReference.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/TypeAnchorReference.java7
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/AST.java55
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java444
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTMatcher.java14
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java209
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java47
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java34
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/RecoveredTypeBinding.java12
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java91
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/NaiveASTFlattener.java21
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java54
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java49
-rw-r--r--org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java2
-rw-r--r--org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java8
-rw-r--r--org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java4
-rw-r--r--org.eclipse.jdt.core/grammar/java.g9
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java55
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java3
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java13
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java12
148 files changed, 8897 insertions, 2489 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TypeAnnotationSyntaxTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TypeAnnotationSyntaxTest.java
index 8be878942..0d1a46d8e 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TypeAnnotationSyntaxTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/TypeAnnotationSyntaxTest.java
@@ -61,7 +61,6 @@ public class TypeAnnotationSyntaxTest extends AbstractSyntaxTreeTest {
}
static final class LocationPrinterVisitor extends ASTVisitor {
- Annotation[] primaryAnnotations;
TypeReference enclosingReference;
Map locations;
@@ -73,13 +72,10 @@ public class TypeAnnotationSyntaxTest extends AbstractSyntaxTreeTest {
return this.locations;
}
public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
- Annotation[] annotations = fieldDeclaration.annotations;
this.enclosingReference = fieldDeclaration.type;
- this.primaryAnnotations = annotations;
return true;
}
public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
- this.primaryAnnotations = methodDeclaration.annotations;
TypeReference returnType = methodDeclaration.returnType;
if (returnType != null) {
this.enclosingReference = returnType;
@@ -90,39 +86,34 @@ public class TypeAnnotationSyntaxTest extends AbstractSyntaxTreeTest {
for (int i = 0; i < thrownExceptionsLength; i++) {
TypeReference typeReference = methodDeclaration.thrownExceptions[i];
this.enclosingReference = typeReference;
- this.primaryAnnotations = null;
typeReference.traverse(this, scope);
}
}
return false;
}
public boolean visit(Argument argument, ClassScope scope) {
- Annotation[] annotations = argument.annotations;
this.enclosingReference = argument.type;
- this.primaryAnnotations = annotations;
return true;
}
public boolean visit(Argument argument, BlockScope scope) {
- Annotation[] annotations = argument.annotations;
this.enclosingReference = argument.type;
- this.primaryAnnotations = annotations;
return true;
}
public boolean visit(MarkerAnnotation annotation, BlockScope scope) {
if (this.enclosingReference != null) {
- storeLocations(annotation, Annotation.getLocations(this.enclosingReference, this.primaryAnnotations, annotation, null, 0));
+ storeLocations(annotation, Annotation.getLocations(this.enclosingReference, annotation));
}
return false;
}
public boolean visit(SingleMemberAnnotation annotation, BlockScope scope) {
if (this.enclosingReference != null) {
- storeLocations(annotation, Annotation.getLocations(this.enclosingReference, this.primaryAnnotations, annotation, null, 0));
+ storeLocations(annotation, Annotation.getLocations(this.enclosingReference, annotation));
}
return false;
}
public boolean visit(NormalAnnotation annotation, BlockScope scope) {
if (this.enclosingReference != null) {
- storeLocations(annotation, Annotation.getLocations(this.enclosingReference, this.primaryAnnotations, annotation, null, 0));
+ storeLocations(annotation, Annotation.getLocations(this.enclosingReference, annotation));
}
return false;
}
@@ -577,7 +568,7 @@ public void test0018() throws IOException {
" public A() {\n" +
" super();\n" +
" }\n" +
- " public @Marker int[] @Marker [][][] @Marker [][] main(HashMap<String, Object>[] @SingleMember(10) [][][] @Normal(Value = 10) [][] args) {\n" +
+ " public @Marker int[] @Marker [][][] @Marker [][] main(HashMap<String, Object>[] @Normal(Value = 10) [][][] @SingleMember(10) [][] args) {\n" +
" }\n" +
"}\n";
checkParse(CHECK_ALL & ~CHECK_JAVAC_PARSER, source.toCharArray(), null, "test0018", expectedUnitToString);
@@ -592,7 +583,7 @@ public void test0019() throws IOException {
" public A() {\n" +
" super();\n" +
" }\n" +
- " public @Marker int[] @Marker [][][] @Marker [][] main(HashMap<String, Object>.Iterator[] @SingleMember(10) [][][] @Normal(Value = 10) [][] args) {\n" +
+ " public @Marker int[] @Marker [][][] @Marker [][] main(HashMap<String, Object>.Iterator[] @Normal(Value = 10) [][][] @SingleMember(10) [][] args) {\n" +
" }\n" +
"}\n";
checkParse(CHECK_ALL & ~CHECK_JAVAC_PARSER, source.toCharArray(), null, "test0019", expectedUnitToString);
@@ -1123,7 +1114,7 @@ public void test0048() throws IOException {
" public A() {\n" +
" super();\n" +
" }\n" +
- " public @Marker HashMap<@Positive Integer, @Negative Integer>[] @NonEmpty [][] foo() {\n" +
+ " public @Marker HashMap<@Positive Integer, @Negative Integer> @NonEmpty [][][] foo() {\n" +
" return null;\n" +
" }\n" +
" public HashMap<@Positive Integer, @Negative Integer>[] @NonEmpty [][] bar() {\n" +
@@ -1143,7 +1134,7 @@ public void test0049() throws IOException {
" public A() {\n" +
" super();\n" +
" }\n" +
- " public @Marker HashMap<@Positive Integer, @Negative Integer>.Iterator[] @NonEmpty [][] foo() {\n" +
+ " public @Marker HashMap<@Positive Integer, @Negative Integer>.Iterator @NonEmpty [][][] foo() {\n" +
" return null;\n" +
" }\n" +
" public HashMap<@Positive Integer, @Negative Integer>.Iterator[] @NonEmpty [][] bar() {\n" +
@@ -1286,8 +1277,8 @@ public void test0056() throws IOException {
" super();\n" +
" }\n" +
" public void foo() {\n" +
- " @Marker HashMap<@Positive Integer, @Negative Integer>[] @NonNull [] @NonEmpty [][] p;\n" +
- " HashMap<@Positive Integer, @Negative Integer>[] @NonNull [] @NonEmpty [][] q;\n" +
+ " @Marker HashMap<@Positive Integer, @Negative Integer> @NonEmpty [][][] @NonNull [] p;\n" +
+ " HashMap<@Positive Integer, @Negative Integer> @NonEmpty [][][] @NonNull [] q;\n" +
" }\n" +
"}\n";
checkParse(CHECK_ALL & ~CHECK_JAVAC_PARSER, source.toCharArray(), null, "test0056", expectedUnitToString);
@@ -1306,7 +1297,7 @@ public void test0057() throws IOException {
" super();\n" +
" }\n" +
" public void foo() {\n" +
- " @Marker HashMap<@Positive Integer, @Negative Integer>.Iterator[] @NonNull [] @NonEmpty [][] p;\n" +
+ " @Marker HashMap<@Positive Integer, @Negative Integer>.Iterator @NonEmpty [][][] @NonNull [] p;\n" +
" HashMap<@Positive Integer, @Negative Integer>.Iterator[] @NonNull [] @NonEmpty [][] q;\n" +
" }\n" +
"}\n";
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
index c6076844c..3d089c094 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java
@@ -104,18 +104,18 @@ public abstract class AbstractRegressionTest extends AbstractCompilerTest implem
" public java.util.Comparator<*> thenComparing(java.util.Comparator<? super *> other) { return null;}\n" +
" public <% extends java.lang.Comparable<? super %>> java.util.Comparator<*> thenComparing(java.util.function.Function<? super *, ? extends %> keyExtractor, java.util.Comparator<? super %> keyComparator) { return null;}\n" +
" public <% extends java.lang.Comparable<? super %>> java.util.Comparator<*> thenComparing(java.util.function.Function<? super *, ? extends %> keyExtractor) { return null;}\n" +
- " public java.util.Comparator<*> thenComparing(java.util.function.ToIntFunction<? super *> keyExtractor) { return null;}\n" +
- " public java.util.Comparator<*> thenComparing(java.util.function.ToLongFunction<? super *> keyExtractor) { return null;}\n" +
- " public java.util.Comparator<*> thenComparing(java.util.function.ToDoubleFunction<? super *> keyExtractor) { return null;}\n";
+ " public java.util.Comparator<*> thenComparingInt(java.util.function.ToIntFunction<? super *> keyExtractor) { return null;}\n" +
+ " public java.util.Comparator<*> thenComparingLong(java.util.function.ToLongFunction<? super *> keyExtractor) { return null;}\n" +
+ " public java.util.Comparator<*> thenComparingDouble(java.util.function.ToDoubleFunction<? super *> keyExtractor) { return null;}\n";
COMPARATOR_RAW_IMPL_JRE8 =
" public java.util.Comparator reverseOrder() { return null;}\n" +
" public java.util.Comparator reversed() { return null;}\n" +
" public java.util.Comparator thenComparing(java.util.Comparator other) { return null;}\n" +
" public java.util.Comparator thenComparing(java.util.function.Function keyExtractor, java.util.Comparator keyComparator) { return null;}\n" +
" public java.util.Comparator thenComparing(java.util.function.Function keyExtractor) { return null;}\n" +
- " public java.util.Comparator thenComparing(java.util.function.ToIntFunction keyExtractor) { return null;}\n" +
- " public java.util.Comparator thenComparing(java.util.function.ToLongFunction keyExtractor) { return null;}\n" +
- " public java.util.Comparator thenComparing(java.util.function.ToDoubleFunction keyExtractor) { return null;}\n";
+ " public java.util.Comparator thenComparingInt(java.util.function.ToIntFunction keyExtractor) { return null;}\n" +
+ " public java.util.Comparator thenComparingLong(java.util.function.ToLongFunction keyExtractor) { return null;}\n" +
+ " public java.util.Comparator thenComparingDouble(java.util.function.ToDoubleFunction keyExtractor) { return null;}\n";
COLLECTION_IMPL_JRE8 =
" public boolean removeAll(java.util.function.Predicate<? super *> filter) { return false;}\n" +
" public boolean removeIf(java.util.function.Predicate<? super *> filter) { return false;}\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java
index e12c96440..d98c8783a 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AnnotationTest.java
@@ -22,6 +22,7 @@
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
* Jesper S Moller - Contributions for
* bug 384567 - [1.5][compiler] Compiler accepts illegal modifiers on package declaration
+ * bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -64,6 +65,8 @@ public class AnnotationTest extends AbstractComparableTest {
}
String reportMissingJavadocComments = null;
+ private String repeatableIntroText;
+ private String repeatableTrailerText;
public AnnotationTest(String name) {
super(name);
@@ -94,6 +97,14 @@ public class AnnotationTest extends AbstractComparableTest {
protected void setUp() throws Exception {
super.setUp();
this.reportMissingJavadocComments = null;
+ this.repeatableIntroText = this.complianceLevel >= ClassFileConstants.JDK1_8 ?
+ "Duplicate annotation of non-repeatable type "
+ :
+ "Duplicate annotation ";
+ this.repeatableTrailerText = this.complianceLevel >= ClassFileConstants.JDK1_8 ?
+ ". Only annotation types marked @Repeatable can be used multiple times at one target.\n"
+ :
+ ". Repeated annotations are allowed only at source level 1.8 or above\n";
}
public void test001() {
@@ -333,12 +344,12 @@ public class AnnotationTest extends AbstractComparableTest {
"1. ERROR in X.java (at line 1)\n" +
" @Foo @Foo\n" +
" ^^^^\n" +
- "Duplicate annotation @Foo\n" +
+ this.repeatableIntroText + "@Foo"+ this.repeatableTrailerText +
"----------\n" +
"2. ERROR in X.java (at line 1)\n" +
" @Foo @Foo\n" +
" ^^^^\n" +
- "Duplicate annotation @Foo\n" +
+ this.repeatableIntroText + "@Foo"+ this.repeatableTrailerText +
"----------\n");
}
@@ -8848,12 +8859,12 @@ public void test266() {
"1. ERROR in p\\package-info.java (at line 1)\n" +
" @Deprecated\n" +
" ^^^^^^^^^^^\n" +
- "Duplicate annotation @Deprecated\n" +
+ this.repeatableIntroText + "@Deprecated"+ this.repeatableTrailerText +
"----------\n" +
"2. ERROR in p\\package-info.java (at line 2)\n" +
" @Deprecated\n" +
" ^^^^^^^^^^^\n" +
- "Duplicate annotation @Deprecated\n" +
+ this.repeatableIntroText + "@Deprecated"+ this.repeatableTrailerText +
"----------\n"
);
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
index c49adf6c7..a0f96f573 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/BatchCompilerTest.java
@@ -2059,7 +2059,8 @@ public void test012b(){
" <option key=\"org.eclipse.jdt.core.compiler.problem.unusedWarningToken\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast\" value=\"warning\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.processAnnotations\" value=\"disabled\"/>\n" +
- " <option key=\"org.eclipse.jdt.core.compiler.source\" value=\"1.5\"/>\n" +
+ " <option key=\"org.eclipse.jdt.core.compiler.source\" value=\"1.5\"/>\n" +
+ " <option key=\"org.eclipse.jdt.core.compiler.storeAnnotations\" value=\"disabled\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.taskCaseSensitive\" value=\"enabled\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.taskPriorities\" value=\"\"/>\n" +
" <option key=\"org.eclipse.jdt.core.compiler.taskTags\" value=\"\"/>\n" +
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
index 9fb25bd9b..fec3c0add 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
@@ -39,6 +39,7 @@
* bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
* bug 382721 - [1.8][compiler] Effectively final variables needs special treatment
* bug 384567 - [1.5][compiler] Compiler accepts illegal modifiers on package declaration
+ * bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -428,6 +429,10 @@ public void _test011_problem_categories() {
expectedProblemAttributes.put("CodeCannotBeReached", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("CodeSnippetMissingClass", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("CodeSnippetMissingMethod", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
+ expectedProblemAttributes.put("ContainingAnnotationHasNonDefaultMembers", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+ expectedProblemAttributes.put("ContainingAnnotationHasShorterRetention", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+ expectedProblemAttributes.put("ContainingAnnotationHasWrongValueType", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+ expectedProblemAttributes.put("ContainingAnnotationMustHaveValue", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("ContradictoryNullAnnotations", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("ContradictoryNullAnnotationsOnBound", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("ComparingIdentical", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
@@ -446,10 +451,12 @@ public void _test011_problem_categories() {
expectedProblemAttributes.put("DereferencingNullableExpression", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("DiamondNotBelow17", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("DirectInvocationOfAbstractMethod", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+ expectedProblemAttributes.put("DisallowedTargetForContainerAnnotation", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("DisallowedTargetForAnnotation", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("DisallowedExplicitThisParameter", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
expectedProblemAttributes.put("DiscouragedReference", new ProblemAttributes(CategorizedProblem.CAT_RESTRICTION));
expectedProblemAttributes.put("DuplicateAnnotation", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+ expectedProblemAttributes.put("DuplicateAnnotationNotMarkedRepeatable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("DuplicateAnnotationMember", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("DuplicateBlankFinalFieldInitialization", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
expectedProblemAttributes.put("DuplicateBounds", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
@@ -526,6 +533,7 @@ public void _test011_problem_categories() {
expectedProblemAttributes.put("IllegalCast", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("IllegalClassLiteralForTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("IllegalDeclarationOfThisParameter", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
+ expectedProblemAttributes.put("IllegalDefaultModifierSpecification", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
expectedProblemAttributes.put("IllegalDefinitionToNonNullParameter", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("IllegalDimension", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
expectedProblemAttributes.put("IllegalEnclosingInstanceSpecification", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
@@ -915,6 +923,11 @@ public void _test011_problem_categories() {
expectedProblemAttributes.put("RequiredNonNullButProvidedSpecdNullable", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("RequiredNonNullButProvidedUnknown", new ProblemAttributes(CategorizedProblem.CAT_POTENTIAL_PROGRAMMING_PROBLEM));
expectedProblemAttributes.put("ReferenceToForwardTypeVariable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+ expectedProblemAttributes.put("RepeatableAnnotationHasTargets", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+ expectedProblemAttributes.put("RepeatableAnnotationIsDocumented", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+ expectedProblemAttributes.put("RepeatableAnnotationIsInherited", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+ expectedProblemAttributes.put("RepeatableAnnotationTargetMismatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
+ expectedProblemAttributes.put("RepeatedAnnotationWithContainerAnnotation", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("ResourceHasToImplementAutoCloseable", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("ReturnTypeAmbiguous", DEPRECATED);
expectedProblemAttributes.put("ReturnTypeCannotBeVoidArray", DEPRECATED);
@@ -1314,6 +1327,10 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("ConstructionTypeMismatch", SKIP);
expectedProblemAttributes.put("ConflictingInheritedNullAnnotations", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
expectedProblemAttributes.put("ConstructorReferenceNotBelow18", SKIP);
+ expectedProblemAttributes.put("ContainingAnnotationHasNonDefaultMembers", SKIP);
+ expectedProblemAttributes.put("ContainingAnnotationHasShorterRetention", SKIP);
+ expectedProblemAttributes.put("ContainingAnnotationHasWrongValueType", SKIP);
+ expectedProblemAttributes.put("ContainingAnnotationMustHaveValue", SKIP);
expectedProblemAttributes.put("ContradictoryNullAnnotations", SKIP);
expectedProblemAttributes.put("ContradictoryNullAnnotationsOnBound", SKIP);
expectedProblemAttributes.put("ConstructorVarargsArgumentNeedCast", new ProblemAttributes(JavaCore.COMPILER_PB_VARARGS_ARGUMENT_NEED_CAST));
@@ -1326,8 +1343,10 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("DiamondNotBelow17", SKIP);
expectedProblemAttributes.put("DirectInvocationOfAbstractMethod", SKIP);
expectedProblemAttributes.put("DisallowedTargetForAnnotation", SKIP);
+ expectedProblemAttributes.put("DisallowedTargetForContainerAnnotation", SKIP);
expectedProblemAttributes.put("DiscouragedReference", new ProblemAttributes(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE));
expectedProblemAttributes.put("DuplicateAnnotation", SKIP);
+ expectedProblemAttributes.put("DuplicateAnnotationNotMarkedRepeatable", SKIP);
expectedProblemAttributes.put("DuplicateAnnotationMember", SKIP);
expectedProblemAttributes.put("DuplicateBlankFinalFieldInitialization", SKIP);
expectedProblemAttributes.put("DuplicateBounds", SKIP);
@@ -1404,6 +1423,7 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("IllegalCast", SKIP);
expectedProblemAttributes.put("IllegalClassLiteralForTypeVariable", SKIP);
expectedProblemAttributes.put("IllegalDeclarationOfThisParameter", SKIP);
+ expectedProblemAttributes.put("IllegalDefaultModifierSpecification", SKIP);
expectedProblemAttributes.put("IllegalDefinitionToNonNullParameter", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
expectedProblemAttributes.put("IllegalDimension", SKIP);
expectedProblemAttributes.put("IllegalEnclosingInstanceSpecification", SKIP);
@@ -1789,6 +1809,11 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("ReferenceExpressionReturnNullRedefUnchecked", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_UNCHECKED_CONVERSION));
expectedProblemAttributes.put("ReferenceToForwardField", SKIP);
expectedProblemAttributes.put("ReferenceToForwardTypeVariable", SKIP);
+ expectedProblemAttributes.put("RepeatableAnnotationHasTargets", SKIP);
+ expectedProblemAttributes.put("RepeatableAnnotationIsDocumented", SKIP);
+ expectedProblemAttributes.put("RepeatableAnnotationIsInherited", SKIP);
+ expectedProblemAttributes.put("RepeatableAnnotationTargetMismatch", SKIP);
+ expectedProblemAttributes.put("RepeatedAnnotationWithContainerAnnotation", SKIP);
expectedProblemAttributes.put("RequiredNonNullButProvidedNull", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_SPECIFICATION_VIOLATION));
expectedProblemAttributes.put("RequiredNonNullButProvidedPotentialNull", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_ANNOTATION_INFERENCE_CONFLICT));
expectedProblemAttributes.put("RequiredNonNullButProvidedUnknown", new ProblemAttributes(JavaCore.COMPILER_PB_NULL_UNCHECKED_CONVERSION));
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest8.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest8.java
index fa8e4f157..f50670fcb 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest8.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/FlowAnalysisTest8.java
@@ -153,7 +153,7 @@ public void testLambda_03() {
"----------\n");
}
-// Lambda with declared args has illegal @NonNull an primitive argument, we now emit an additional not-invalid message.
+// Lambda with declared args has illegal @NonNull an primitive argument
public void testLambda_04() {
Map customOptions = getCompilerOptions();
runNegativeTestWithLibs(
@@ -177,11 +177,6 @@ public void testLambda_04() {
" ISAM printer1 = (@NonNull int i) \n" +
" ^^^^^^^^\n" +
"The nullness annotation @NonNull is not applicable for the primitive type int\n" +
- "----------\n" +
- "2. ERROR in X.java (at line 4)\n" +
- " ISAM printer1 = (@NonNull int i) \n" +
- " ^^^^^^^^^^^^\n" +
- "Illegal redefinition of parameter i, inherited method from ISAM does not constrain this parameter\n" +
"----------\n");
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GrammarCoverageTests308.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GrammarCoverageTests308.java
index 5ba0ab8ff..9d9aecb84 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GrammarCoverageTests308.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GrammarCoverageTests308.java
@@ -975,8 +975,7 @@ public class GrammarCoverageTests308 extends AbstractRegressionTest {
// TypeParameter ::= TypeParameterHeader 'extends' ReferenceType AdditionalBoundList
// AdditionalBound ::= '&' ReferenceType
// TypeParameter1 ::= TypeParameterHeader 'extends' ReferenceType AdditionalBoundList1
- // TODO(Srikanth): fix and re-enable test.
- public void _test023() throws Exception {
+ public void test023() throws Exception {
this.runNegativeTest(
new String[] {
"I.java",
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeTypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeTypeAnnotationTest.java
index 3d9e27cfb..3ffd81ff1 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeTypeAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NegativeTypeAnnotationTest.java
@@ -3427,4 +3427,660 @@ public class NegativeTypeAnnotationTest extends AbstractRegressionTest {
"p.q cannot be resolved to a type\n" +
"----------\n");
}
-}
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=417076, Eclipse compiler rejects multiple annotations for varargs.
+ public void test417076() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface A {\n" +
+ "}\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface B {\n" +
+ "}\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface C {\n" +
+ "}\n" +
+ "public class X {\n" +
+ " public @A String foo(int @B @C @D ... args) {\n" +
+ " return null;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 13)\n" +
+ " public @A String foo(int @B @C @D ... args) {\n" +
+ " ^\n" +
+ "D cannot be resolved to a type\n" +
+ "----------\n");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=417076, Eclipse compiler rejects multiple annotations for varargs.
+ public void test417076b() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface A {\n" +
+ "}\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface B {\n" +
+ "}\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface C {\n" +
+ "}\n" +
+ "public class X {\n" +
+ " public @A String foo(int @B @C @A ... args) {\n" +
+ " return null;\n" +
+ " }\n" +
+ " public @A String goo(int @B @C @A ... args) {\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 16)\n" +
+ " public @A String goo(int @B @C @A ... args) {\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "This method must return a result of type String\n" +
+ "----------\n");
+ }
+ // [1.8][compiler] Illegal type annotations not rejected (https://bugs.eclipse.org/bugs/show_bug.cgi?id=415308)
+ // This is the basic test case which demonstrated the issue for a local variable.
+ // We correctly identified the problem in function bar but failed to do so for foo.
+ public void test415308a() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface Illegal {\n" +
+ "}\n" +
+ "class Y {\n" +
+ " static class Z {\n" +
+ " Z() {}\n" +
+ " }\n" +
+ "}\n" +
+ "class X {\n" +
+ " Y.Z foo() {\n" +
+ " @Illegal Y.Z z = null;\n" +
+ " return z;\n" +
+ " }\n" +
+ " Y.Z bar() {\n" +
+ " Y.Z z = (@Illegal Y.Z)null;\n" +
+ " return z;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 14)\n" +
+ " @Illegal Y.Z z = null;\n" +
+ " ^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 18)\n" +
+ " Y.Z z = (@Illegal Y.Z)null;\n" +
+ " ^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n");
+ }
+ // [1.8][compiler] Illegal type annotations not rejected (https://bugs.eclipse.org/bugs/show_bug.cgi?id=415308)
+ // This test case is similar to test415308a. SimpleTypes on which annotations are applied are modified to array
+ // types.
+ public void test415308a2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface Illegal {\n" +
+ "}\n" +
+ "class Y {\n" +
+ " static class Z {\n" +
+ " Z() {}\n" +
+ " }\n" +
+ "}\n" +
+ "class X {\n" +
+ " Y.Z[] foo() {\n" +
+ " @Illegal Y.Z[] z = null;\n" +
+ " return z;\n" +
+ " }\n" +
+ " Y.Z[] bar() {\n" +
+ " Y.Z[] z = (@Illegal Y.Z[])null;\n" +
+ " return z;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 14)\n" +
+ " @Illegal Y.Z[] z = null;\n" +
+ " ^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 18)\n" +
+ " Y.Z[] z = (@Illegal Y.Z[])null;\n" +
+ " ^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n");
+ }
+ // [1.8][compiler] Illegal type annotations not rejected (https://bugs.eclipse.org/bugs/show_bug.cgi?id=415308)
+ // Testing type use annotations on nested types.
+ // We check all the qualifiers as we look for a static type. This test checks if we are able to
+ // go beyond 1 level as part of the loop.
+ public void test415308b() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface Illegal {\n" +
+ "}\n" +
+ "class Y {\n" +
+ " static class YY {\n" +
+ " class Z {\n" +
+ " Z() {}\n" +
+ " }\n" +
+ " }\n" +
+ "}\n" +
+ "class X {\n" +
+ " Y.YY.Z foo() {\n" +
+ " @Illegal Y.YY.Z z = null;\n" +
+ " return z;\n" +
+ " }\n" +
+ " Y.YY.Z foo2() {\n" +
+ " Y.@Illegal YY.Z z = null;\n" +
+ " return z;\n" +
+ " }\n" +
+ " Y.YY.Z foo3() {\n" +
+ " Y.YY.@Illegal Z z = null;\n" +
+ " return z;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 16)\n" +
+ " @Illegal Y.YY.Z z = null;\n" +
+ " ^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n");
+ }
+ // [1.8][compiler] Illegal type annotations not rejected (https://bugs.eclipse.org/bugs/show_bug.cgi?id=415308)
+ // This test case is similar to test415308a. SimpleTypes on which annotations are applied are modified to array
+ // types.
+ public void test415308b2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface Illegal {\n" +
+ "}\n" +
+ "class Y {\n" +
+ " static class YY {\n" +
+ " class Z {\n" +
+ " Z() {}\n" +
+ " }\n" +
+ " }\n" +
+ "}\n" +
+ "class X {\n" +
+ " Y.YY.Z[] foo() {\n" +
+ " @Illegal Y.YY.Z[] z = null;\n" +
+ " return z;\n" +
+ " }\n" +
+ " Y.YY.Z[] foo2() {\n" +
+ " Y.@Illegal YY.Z[] z = null;\n" +
+ " return z;\n" +
+ " }\n" +
+ " Y.YY.Z[] foo3() {\n" +
+ " Y.YY.@Illegal Z[] z = null;\n" +
+ " return z;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 16)\n" +
+ " @Illegal Y.YY.Z[] z = null;\n" +
+ " ^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n");
+ }
+ // [1.8][compiler] Illegal type annotations not rejected (https://bugs.eclipse.org/bugs/show_bug.cgi?id=415308)
+ // The test case is to validate that we report errors for only type annotations and nothing else in case of
+ // of parameter types.
+ public void test415308c() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface IllegalTypeUse {\n" +
+ "}\n" +
+ "@Target({ElementType.TYPE_USE, ElementType.PARAMETER})\n" +
+ "@interface LegalTypeUseParam {\n" +
+ "}\n" +
+ "@Target(ElementType.PARAMETER)\n" +
+ "@interface LegalParam {\n" +
+ "}\n" +
+ "class Y {\n" +
+ " static class Z {\n" +
+ " Z() {}\n" +
+ " }\n" +
+ "}\n" +
+ "class X {\n" +
+ " Y.Z foo(@LegalParam Y.Z z) { //Legal\n" +
+ " return z;\n" +
+ " }\n" +
+ " Y.Z foo2(@LegalTypeUseParam Y.Z z) { //Legal\n" +
+ " return z;\n" +
+ " }\n" +
+ " Y.Z foo3(@IllegalTypeUse @LegalParam Y.Z z) { //Illegal\n" +
+ " return z;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 25)\n" +
+ " Y.Z foo3(@IllegalTypeUse @LegalParam Y.Z z) { //Illegal\n" +
+ " ^^^^^^^^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n");
+ }
+ //[1.8][compiler] Illegal type annotations not rejected (https://bugs.eclipse.org/bugs/show_bug.cgi?id=415308)
+ //The test case is to validate type use annotation for class fields.
+ public void test415308d() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface Illegal {\n" +
+ "}\n" +
+ "class Y {\n" +
+ " static class Z {\n" +
+ " Z() {}\n" +
+ " }\n" +
+ "}\n" +
+ "class X {\n" +
+ " @Illegal \n" +
+ " Y.Z z;\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 13)\n" +
+ " @Illegal \n" +
+ " ^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n");
+ }
+ //[1.8][compiler] Illegal type annotations not rejected (https://bugs.eclipse.org/bugs/show_bug.cgi?id=415308)
+ //The test case checks for annotations which are not exclusively TYPE_USE. We should not report a error.
+ public void test415308d2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "\n" +
+ "@Target({ElementType.TYPE_USE, ElementType.FIELD})\n" +
+ "@interface Legal {\n" +
+ "}\n" +
+ "class Y {\n" +
+ " static class Z {\n" +
+ " Z() {}\n" +
+ " }\n" +
+ "}\n" +
+ "class X {\n" +
+ " @Legal \n" +
+ " Y.Z z;\n" +
+ "}\n"
+ },
+ "");
+ }
+ //[1.8][compiler] Illegal type annotations not rejected (https://bugs.eclipse.org/bugs/show_bug.cgi?id=415308)
+ //The test case is to validate type use annotation for class fields.
+ //We check all the qualifiers as we look for a static type. This test checks if we are able to
+ //go beyond 1 level as part of the loop.
+ public void test415308e() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface Illegal {\n" +
+ "}\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface Illegal2 {\n" +
+ "}\n" +
+ "@Target(ElementType.FIELD)\n" +
+ "@interface Legal {\n" +
+ "}\n" +
+ "class Y {\n" +
+ " static class YY {\n" +
+ " class Z {\n" +
+ " Z() {}\n" +
+ " }\n" +
+ " }\n" +
+ "}\n" +
+ "class X {\n" +
+ " @Legal @Illegal @Illegal2\n" +
+ " Y.YY.Z z;\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 21)\n" +
+ " @Legal @Illegal @Illegal2\n" +
+ " ^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 21)\n" +
+ " @Legal @Illegal @Illegal2\n" +
+ " ^^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n");
+ }
+ // [1.8][compiler] Illegal type annotations not rejected (https://bugs.eclipse.org/bugs/show_bug.cgi?id=415308)
+ // The test case is to validate type use annotations on return types for methods.
+ public void test415308f() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface Illegal {\n" +
+ "}\n" +
+ "class Y {\n" +
+ " static class Z {\n" +
+ " Z() {}\n" +
+ " }\n" +
+ "}\n" +
+ "class X {\n" +
+ " public @Illegal Y.Z foo() { return null;}\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 13)\n" +
+ " public @Illegal Y.Z foo() { return null;}\n" +
+ " ^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n");
+ }
+ // [1.8][compiler] Illegal type annotations not rejected (https://bugs.eclipse.org/bugs/show_bug.cgi?id=415308)
+ // The test case is a array version of test415308f.
+ public void test415308f2() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface Illegal {\n" +
+ "}\n" +
+ "class Y {\n" +
+ " static class Z {\n" +
+ " Z() {}\n" +
+ " }\n" +
+ "}\n" +
+ "class X {\n" +
+ " public @Illegal Y.Z[] foo() { return null;}\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 13)\n" +
+ " public @Illegal Y.Z[] foo() { return null;}\n" +
+ " ^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n");
+ }
+ // [1.8][compiler] Illegal type annotations not rejected (https://bugs.eclipse.org/bugs/show_bug.cgi?id=415308)
+ // The test case is used to test enums with type annotations.
+ public void test415308g() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface Illegal {\n" +
+ "}\n" +
+ "class Y {\n" +
+ " enum A { B }\n" +
+ "}\n" +
+ "class X {\n" +
+ " @Illegal Y.A foo(@Illegal Y.A a) {\n" +
+ " return a;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 11)\n" +
+ " @Illegal Y.A foo(@Illegal Y.A a) {\n" +
+ " ^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 11)\n" +
+ " @Illegal Y.A foo(@Illegal Y.A a) {\n" +
+ " ^^^^^^^^\n" +
+ "Type annotations are not allowed on type names used to access static members\n" +
+ "----------\n");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=418041, NPE during AST creation.
+ public void test418041() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "import java.util.List;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface Readonly {\n" +
+ "}\n" +
+ "class UnmodifiableList<T> implements\n" +
+ "@Readonly List<@Readonly T> { }\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.addAll(int, Collection<? extends T>)\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.addAll(Collection<? extends T>)\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.lastIndexOf(Object)\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.subList(int, int)\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.contains(Object)\n" +
+ "----------\n" +
+ "6. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.get(int)\n" +
+ "----------\n" +
+ "7. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.retainAll(Collection<?>)\n" +
+ "----------\n" +
+ "8. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.clear()\n" +
+ "----------\n" +
+ "9. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.indexOf(Object)\n" +
+ "----------\n" +
+ "10. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.toArray(T[])\n" +
+ "----------\n" +
+ "11. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.toArray()\n" +
+ "----------\n" +
+ "12. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.isEmpty()\n" +
+ "----------\n" +
+ "13. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.listIterator(int)\n" +
+ "----------\n" +
+ "14. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.listIterator()\n" +
+ "----------\n" +
+ "15. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.add(int, T)\n" +
+ "----------\n" +
+ "16. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.add(T)\n" +
+ "----------\n" +
+ "17. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.set(int, T)\n" +
+ "----------\n" +
+ "18. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.size()\n" +
+ "----------\n" +
+ "19. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.containsAll(Collection<?>)\n" +
+ "----------\n" +
+ "20. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.remove(int)\n" +
+ "----------\n" +
+ "21. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.remove(Object)\n" +
+ "----------\n" +
+ "22. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.removeAll(Collection<?>)\n" +
+ "----------\n" +
+ "23. ERROR in X.java (at line 7)\n" +
+ " class UnmodifiableList<T> implements\n" +
+ " ^^^^^^^^^^^^^^^^\n" +
+ "The type UnmodifiableList<T> must implement the inherited abstract method List<T>.iterator()\n" +
+ "----------\n");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=418041, NPE during AST creation.
+ public void test418041a() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public class X <@Marker T extends @Marker Y<@Marker ?>, @Marker Q extends @Marker Integer> {\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 1)\n" +
+ " public class X <@Marker T extends @Marker Y<@Marker ?>, @Marker Q extends @Marker Integer> {\n" +
+ " ^^^^^^^^^\n" +
+ "Y cannot be resolved to a type\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 1)\n" +
+ " public class X <@Marker T extends @Marker Y<@Marker ?>, @Marker Q extends @Marker Integer> {\n" +
+ " ^^^^^^^^^^^^^^^\n" +
+ "The type parameter Q should not be bounded by the final type Integer. Final types cannot be further extended\n" +
+ "----------\n");
+ }
+ public void testWildcardCapture() {
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "import java.util.List;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface NonNull {\n" +
+ "}\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface Nullable {\n" +
+ "}\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ "}\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " List<@Nullable ? extends X> lx1 = null;\n" +
+ " List<@NonNull ? extends X> lx2 = null;\n" +
+ " lx1 = lx2;\n" +
+ " lx1.add(lx2.get(0));\n" +
+ " lx1.add(lx1.get(0));\n" +
+ " getAdd(lx1, lx2);\n" +
+ " }\n" +
+ " static <@NonNull P> void getAdd(List<P> p1, List<P> p2) {\n" +
+ " p1.add(p2.get(0));\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 18)\n" +
+ " lx1.add(lx2.get(0));\n" +
+ " ^^^\n" +
+ "The method add(capture#3-of ? extends X) in the type List<capture#3-of ? extends X> is not applicable for the arguments (capture#4-of ? extends X)\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 19)\n" +
+ " lx1.add(lx1.get(0));\n" +
+ " ^^^\n" +
+ "The method add(capture#5-of ? extends X) in the type List<capture#5-of ? extends X> is not applicable for the arguments (capture#6-of ? extends X)\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 20)\n" +
+ " getAdd(lx1, lx2);\n" +
+ " ^^^^^^\n" +
+ "The method getAdd(List<P>, List<P>) in the type X is not applicable for the arguments (List<capture#7-of ? extends X>, List<capture#8-of ? extends X>)\n" +
+ "----------\n");
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
index a42b4eaaa..303cb49a0 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullAnnotationTest.java
@@ -36,7 +36,7 @@ public NullAnnotationTest(String name) {
// Static initializer to specify tests subset using TESTS_* static variables
// All specified tests which do not belong to the class are skipped...
static {
-// TESTS_NAMES = new String[] { "test_nonnull_var_in_constrol_structure_1" };
+// TESTS_NAMES = new String[] { "testBug412076" };
// TESTS_NUMBERS = new int[] { 561 };
// TESTS_RANGE = new int[] { 1, 2049 };
}
@@ -111,6 +111,16 @@ String nonNullArrayOf(String string) {
: "Object @NonNull[]";
}
+
+String targetTypeUseIfAvailable() {
+ return this.complianceLevel >= ClassFileConstants.JDK1_8
+ ? "@Target(ElementType.TYPE_USE)\n"
+ : "";
+}
+
+/**
+ * @deprecated
+ */
protected void setUp() throws Exception {
super.setUp();
if (this.complianceLevel >= ClassFileConstants.JDK1_8)
@@ -535,7 +545,10 @@ public void test_nonnull_parameter_015() {
" if (o != null)\n" +
" System.out.print(o.toString());\n" +
" }\n" +
- " void foo2(int i, @NonNull Object ... o) {\n" +
+ ((this.complianceLevel < ClassFileConstants.JDK1_8)
+ ? " void foo2(int i, @NonNull Object ... o) {\n"
+ : " void foo2(int i, Object @NonNull ... o) {\n"
+ ) +
" if (o.length > 0 && o[0] != null)\n" +
" System.out.print(o[0].toString());\n" +
" }\n" +
@@ -1939,17 +1952,19 @@ public void test_annotation_import_005() {
"package org.foo;\n" +
"import java.lang.annotation.*;\n" +
"@Retention(RetentionPolicy.CLASS)\n" +
+ targetTypeUseIfAvailable() +
"public @interface MayBeNull {}\n",
"org/foo/MustNotBeNull.java",
"package org.foo;\n" +
"import java.lang.annotation.*;\n" +
"@Retention(RetentionPolicy.CLASS)\n" +
+ targetTypeUseIfAvailable() +
"public @interface MustNotBeNull {}\n",
"Lib.java",
"public class Lib {\n" +
- " Object getObject() { return new Object(); }\n" +
+ " public Object getObject() { return new Object(); }\n" +
"}\n",
"X.java",
"import org.foo.*;\n" +
@@ -6154,81 +6169,6 @@ public void test_conditional_expression_1() {
"----------\n");
}
-// missing type in constructor declaration must not cause NPE in QAE#resolveType(..)
-public void testBug415850_a() {
- this.runNegativeTest(
- new String[] {
- "X.java", //-----------------------------------------------------------------------
- "public class X {\n" +
- " void foo(X1 x1) {\n" +
- " Object o = new X1(x1){};\n" +
- " }\n" +
- "}\n",
- "X1.java", //-----------------------------------------------------------------------
- "public class X1 {\n" +
- " public X1(Zork z) {}\n" +
- "}\n"
- },
- "----------\n" +
- "1. ERROR in X.java (at line 3)\n" +
- " Object o = new X1(x1){};\n" +
- " ^^^^^^\n" +
- "The constructor X1(Zork) refers to the missing type Zork\n" +
- "----------\n" +
- "----------\n" +
- "1. ERROR in X1.java (at line 2)\n" +
- " public X1(Zork z) {}\n" +
- " ^^^^\n" +
- "Zork cannot be resolved to a type\n" +
- "----------\n");
-}
-
-// avoid NPE in BinaryTypeBinding.getField(..) due to recursive dependency enum->package-info->annotation->enum
-public void testBug415850_b() {
- runConformTestWithLibs(
- new String[] {
- "p/package-info.java",
- "@p.Annot(state=p.MyEnum.BROKEN)\n" +
- "package p;",
- "p/Annot.java",
- "package p;\n" +
- "@Annot(state=MyEnum.KO)\n" +
- "public @interface Annot {\n" +
- " MyEnum state() default MyEnum.KO;\n" +
- "}",
- "p/MyEnum.java",
- "package p;\n" +
- "@Annot(state=MyEnum.KO)\n" +
- "public enum MyEnum {\n" +
- " WORKS, OK, KO, BROKEN, ;\n" +
- "}",
- "test180/Test.java",
- "package test180;\n" +
- "import p.MyEnum;\n" +
- "import p.Annot;\n" +
- "@Annot(state=MyEnum.OK)\n" +
- "public class Test {}",
- },
- getCompilerOptions(),
- ""
- );
- Map options = getCompilerOptions();
- options.put(CompilerOptions.OPTION_Process_Annotations, CompilerOptions.ENABLED);
- runConformTestWithLibs(
- new String[] {
- "X.java",
- "import test180.Test;\n" +
- "public class X {\n" +
- " public static void main(String[] args) {\n" +
- " System.out.println(Test.class);\n" +
- " }\n" +
- "}"
- },
- options,
- "",
- "class test180.Test");
-}
-
// Bug 403086 - [compiler][null] include the effect of 'assert' in syntactic null analysis for fields
public void testBug403086_1() {
Map customOptions = getCompilerOptions();
@@ -6322,4 +6262,188 @@ public void testBug412076() {
options,
"");
}
+
+public void testBug413460() {
+ runConformTestWithLibs(
+ new String[] {
+ "Class2.java",
+ "\n" +
+ "@org.eclipse.jdt.annotation.NonNullByDefault\n" +
+ "public class Class2 {\n" +
+ " public class Class3 {\n" +
+ " public Class3(String nonNullArg) {\n" +
+ " assert nonNullArg != null;\n" +
+ " }\n" +
+ " }\n" +
+ "\n" +
+ " public Class2(String nonNullArg) {\n" +
+ " assert nonNullArg != null;\n" +
+ " }\n" +
+ "\n" +
+ " public static Class2 create(String nonNullArg) {\n" +
+ " return new Class2(nonNullArg);\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "");
+ runNegativeTestWithLibs(false,
+ new String[] {
+ "Class1.java",
+ "public class Class1 {\n" +
+ " public static Class2 works() {\n" +
+ " return Class2.create(null);\n" +
+ " }\n" +
+ "\n" +
+ " public static Class2 bug() {\n" +
+ " return new Class2(null);\n" +
+ " }\n" +
+ "\n" +
+ " public static Class2.Class3 qualifiedbug() {\n" +
+ " return new Class2(\"\").new Class3(null);\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in Class1.java (at line 3)\n" +
+ " return Class2.create(null);\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String\' but the provided value is null\n" +
+ "----------\n" +
+ "2. ERROR in Class1.java (at line 7)\n" +
+ " return new Class2(null);\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String\' but the provided value is null\n" +
+ "----------\n" +
+ "3. ERROR in Class1.java (at line 11)\n" +
+ " return new Class2(\"\").new Class3(null);\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String\' but the provided value is null\n" +
+ "----------\n");
+}
+
+// missing type in constructor declaration must not cause NPE in QAE#resolveType(..)
+public void testBug415850_a() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java", //-----------------------------------------------------------------------
+ "public class X {\n" +
+ " void foo(X1 x1) {\n" +
+ " Object o = new X1(x1){};\n" +
+ " }\n" +
+ "}\n",
+ "X1.java", //-----------------------------------------------------------------------
+ "public class X1 {\n" +
+ " public X1(Zork z) {}\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " Object o = new X1(x1){};\n" +
+ " ^^^^^^\n" +
+ "The constructor X1(Zork) refers to the missing type Zork\n" +
+ "----------\n" +
+ "----------\n" +
+ "1. ERROR in X1.java (at line 2)\n" +
+ " public X1(Zork z) {}\n" +
+ " ^^^^\n" +
+ "Zork cannot be resolved to a type\n" +
+ "----------\n");
+}
+
+// avoid NPE in BinaryTypeBinding.getField(..) due to recursive dependency enum->package-info->annotation->enum
+public void testBug415850_b() {
+ runConformTestWithLibs(
+ new String[] {
+ "p/package-info.java",
+ "@p.Annot(state=p.MyEnum.BROKEN)\n" +
+ "package p;",
+ "p/Annot.java",
+ "package p;\n" +
+ "@Annot(state=MyEnum.KO)\n" +
+ "public @interface Annot {\n" +
+ " MyEnum state() default MyEnum.KO;\n" +
+ "}",
+ "p/MyEnum.java",
+ "package p;\n" +
+ "@Annot(state=MyEnum.KO)\n" +
+ "public enum MyEnum {\n" +
+ " WORKS, OK, KO, BROKEN, ;\n" +
+ "}",
+ "test180/Test.java",
+ "package test180;\n" +
+ "import p.MyEnum;\n" +
+ "import p.Annot;\n" +
+ "@Annot(state=MyEnum.OK)\n" +
+ "public class Test {}",
+ },
+ getCompilerOptions(),
+ ""
+ );
+ Map options = getCompilerOptions();
+ options.put(CompilerOptions.OPTION_Process_Annotations, CompilerOptions.ENABLED);
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import test180.Test;\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " System.out.println(Test.class);\n" +
+ " }\n" +
+ "}"
+ },
+ options,
+ "",
+ "class test180.Test");
+}
+public void testBug417295_5() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "AllAreNonNull.java",
+ "@org.eclipse.jdt.annotation.NonNullByDefault\n" +
+ "public class AllAreNonNull {\n" +
+ " String s3 = \"\";\n" +
+ " void test() {\n" +
+ " this.s3 = null;\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in AllAreNonNull.java (at line 5)\n" +
+ " this.s3 = null;\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String\' but the provided value is null\n" +
+ "----------\n");
+}
+public void testBug417295_7() {
+ runConformTestWithLibs(
+ new String[] {
+ "p1/AllAreNonNull.java",
+ "package p1;\n" +
+ "@org.eclipse.jdt.annotation.NonNullByDefault\n" +
+ "public class AllAreNonNull {\n" +
+ " public String s3 = \"\";\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "");
+ runNegativeTestWithLibs(
+ false,
+ new String[] {
+ "Client.java",
+ "public class Client {\n" +
+ " void test(p1.AllAreNonNull aann) {\n" +
+ " aann.s3 = null;\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in Client.java (at line 3)\n" +
+ " aann.s3 = null;\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String\' but the provided value is null\n" +
+ "----------\n");
+}
}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
index 3f214c299..b3c6764ee 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
@@ -29,7 +29,7 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
// Static initializer to specify tests subset using TESTS_* static variables
// All specified tests which do not belong to the class are skipped...
static {
-// TESTS_NAMES = new String[] { "testCompatibility6" };
+// TESTS_NAMES = new String[] { "testConditional2" };
// TESTS_NUMBERS = new int[] { 561 };
// TESTS_RANGE = new int[] { 1, 2049 };
}
@@ -1030,7 +1030,6 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
}
// storing and decoding null-type-annotations to/from classfile: CLASS_TYPE_PARAMETER & METHOD_TYPE_PARAMETER
- // TODO(Stephan) : 3rd error message looks weird. We need to clone and set the bits for allocation expression or otherwise handle.
public void testBinary05() {
Map customOptions = getCompilerOptions();
customOptions.put(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE, JavaCore.ERROR);
@@ -1070,13 +1069,7 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
" x.<@NonNull Object>foo(new Object());\n" +
" ^^^^^^^^^^^^^^^\n" +
"Null constraint mismatch: The type \'@NonNull Object\' is not a valid substitute for the type parameter \'S\' which is constrained as \'@Nullable\'\n" +
- "----------\n" +
- "3. WARNING in Y1.java (at line 6)\n" +
- " x.<@NonNull Object>foo(new Object());\n" +
- " ^^^^^^^^^^^^\n" +
- "Null type safety (type annotations): The expression of type \'Object\' needs unchecked conversion to conform to \'@NonNull Object\'\n" +
- "----------\n"
- );
+ "----------\n");
}
// storing and decoding null-type-annotations to/from classfile: CLASS_TYPE_PARAMETER_BOUND & METHOD_TYPE_PARAMETER_BOUND
@@ -1366,7 +1359,7 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
"5. ERROR in Y1.java (at line 11)\n" +
" x.wildcard1(new ArrayList<@NonNull X1>()); // incompatible(2)\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Null type mismatch (type annotations): required \'List<@Nullable ? extends p.X1>\' but this expression has type \'ArrayList<@NonNull X1>\', corresponding supertype is \'List<@NonNull X1>\'\n" +
+ "Null type mismatch (type annotations): required \'List<@Nullable ? extends X1>\' but this expression has type \'ArrayList<@NonNull X1>\', corresponding supertype is \'List<@NonNull X1>\'\n" +
"----------\n");
}
@@ -1456,10 +1449,150 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
"5. ERROR in Y1.java (at line 11)\n" +
" x.wildcard1(new ArrayList<p.@NonNull X1>()); // incompatible(2)\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Null type mismatch (type annotations): required \'List<@Nullable ? extends p.X1>\' but this expression has type \'ArrayList<@NonNull X1>\', corresponding supertype is \'List<@NonNull X1>\'\n" +
+ "Null type mismatch (type annotations): required \'List<@Nullable ? extends X1>\' but this expression has type \'ArrayList<@NonNull X1>\', corresponding supertype is \'List<@NonNull X1>\'\n" +
"----------\n");
}
- // TODO(Stephan): Fix lub computation to create an intersection type when annotations differ. See comment in Scope#lowerUpperBound.
+
+ // storing and decoding null-type-annotations to/from classfile: EXTENDED DIMENSIONS.
+ public void testBinary09() {
+ Map customOptions = getCompilerOptions();
+ customOptions.put(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE, JavaCore.ERROR);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "public class X {\n" +
+ " @NonNull String @Nullable [] f @NonNull [] = null;\n" +
+ " static void foo(@NonNull String @Nullable [] p @NonNull []) {\n" +
+ " p = null;\n" +
+ " @NonNull String @Nullable [] l @NonNull [] = null;\n" +
+ " }\n" +
+ "}\n"
+
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " @NonNull String @Nullable [] f @NonNull [] = null;\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String @NonNull[] @Nullable[]\' but the provided value is null\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 6)\n" +
+ " p = null;\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String @NonNull[] @Nullable[]\' but the provided value is null\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 7)\n" +
+ " @NonNull String @Nullable [] l @NonNull [] = null;\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String @NonNull[] @Nullable[]\' but the provided value is null\n" +
+ "----------\n");
+ // fix the error:
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "public class X {\n" +
+ " @NonNull String @Nullable [] f @NonNull [] = new @NonNull String @Nullable [0] @NonNull [];\n" +
+ "}\n"
+ },
+ customOptions,
+ "");
+
+ runNegativeTestWithLibs(
+ new String[] {
+ "Y.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "public class Y {\n" +
+ " void test(X x) {\n" +
+ " x.f = null;\n" +
+ " x.f[0] = null;\n" +
+ " x.f[0][0] = null;\n" +
+ " }\n" +
+ "}\n"
+ },
+ customOptions,
+ "----------\n" +
+ "1. WARNING in Y.java (at line 1)\n" +
+ " import org.eclipse.jdt.annotation.*;\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "The import org.eclipse.jdt.annotation is never used\n" +
+ "----------\n" +
+ "2. ERROR in Y.java (at line 4)\n" +
+ " x.f = null;\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String @NonNull[] @Nullable[]\' but the provided value is null\n" +
+ "----------\n" +
+ "3. ERROR in Y.java (at line 6)\n" +
+ " x.f[0][0] = null;\n" +
+ " ^^^^^^\n" +
+ "Potential null pointer access: array element may be null\n" +
+ "----------\n" +
+ "4. ERROR in Y.java (at line 6)\n" +
+ " x.f[0][0] = null;\n" +
+ " ^^^^^^^^^\n" +
+ "Null type mismatch: required \'@NonNull String\' but the provided value is null\n" +
+ "----------\n");
+}
+
+ // storing and decoding null-type-annotations to/from classfile: array annotations.
+ public void testBinary10() {
+ Map customOptions = getCompilerOptions();
+ customOptions.put(JavaCore.COMPILER_PB_POTENTIAL_NULL_REFERENCE, JavaCore.ERROR);
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.util.ArrayList;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "public class X {\n" +
+ " void foo(ArrayList<String> @NonNull [] p) {\n" +
+ " }\n" +
+ "}\n" +
+ "class Y extends X {\n" +
+ " void foo() {\n" +
+ " super.foo(null);\n" +
+ " }\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " super.foo(null);\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'ArrayList<String> @NonNull[]\' but the provided value is null\n" +
+ "----------\n");
+ // fix the error:
+ runConformTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.util.ArrayList;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "public class X {\n" +
+ " void foo(ArrayList<String> @NonNull [] p) {\n" +
+ " }\n" +
+ "}\n"
+ },
+ customOptions,
+ "");
+
+ runNegativeTestWithLibs(
+ new String[] {
+ "Y.java",
+ "public class Y extends X {\n" +
+ " void foo() {\n" +
+ " super.foo(null);\n" +
+ " }\n" +
+ "}\n"
+ },
+ customOptions,
+ "----------\n" +
+ "1. ERROR in Y.java (at line 3)\n" +
+ " super.foo(null);\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'ArrayList<String> @NonNull[]\' but the provided value is null\n" +
+ "----------\n");
+ }
+
public void testConditional1() {
runNegativeTestWithLibs(
new String[] {
@@ -1479,7 +1612,43 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
+ "}\n"
},
"----------\n" +
- "1. WARNING in X.java (at line 8)\n" +
+ "1. WARNING in X.java (at line 6)\n" +
+ " return f == 0 ? good : dubious;\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Null type safety (type annotations): The expression of type \'List<String>\' needs unchecked conversion to conform to \'List<@NonNull String>\'\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 8)\n" +
+ " return f == 2 ? dubious : good;\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Null type safety (type annotations): The expression of type \'List<String>\' needs unchecked conversion to conform to \'List<@NonNull String>\'\n" +
+ "----------\n");
+ }
+
+ public void _testConditional2() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n"
+ + "import java.util.*;\n"
+ + "public class X {\n"
+ + " List<@NonNull String> foo(List<@NonNull String> good, ArrayList<String> dubious, int f) {\n"
+ + " if (f < 2)\n"
+ + " return f == 0 ? good : dubious;\n"
+ + " if (f < 4)\n"
+ + " return f == 2 ? dubious : good;\n"
+ + " if (f < 6)\n"
+ + " return f == 4 ? good : good;\n"
+ + " return null;\n"
+ + " }\n"
+ + "}\n"
+ },
+ "----------\n" +
+ "1. WARNING in X.java (at line 6)\n" +
+ " return f == 0 ? good : dubious;\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Null type safety (type annotations): The expression of type \'List<String>\' needs unchecked conversion to conform to \'List<@NonNull String>\'\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 8)\n" +
" return f == 2 ? dubious : good;\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Null type safety (type annotations): The expression of type \'List<String>\' needs unchecked conversion to conform to \'List<@NonNull String>\'\n" +
@@ -1668,7 +1837,6 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
}
// types without null annotations are converted (unsafe) to types with detail annotations (array content)
- // FIXME(Stephan) : Old messages are wrong, the new diagnostics are correct, but the leaf component types differ - null annotated readable names don't reflect that - this needs to be fixed.
public void testCompatibility3a() {
runNegativeTestWithLibs(
new String[] {
@@ -1689,7 +1857,7 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
+ " acceptNulls(dubious);\n"
+ " acceptNoNulls(dubious);\n"
+ " }\n"
- + " void acceptNulls(@NonNull String[] noNulls) {}\n"
+ + " void acceptNulls(@Nullable String[] withNulls) {}\n"
+ " void acceptNoNulls(@NonNull String[] noNulls) {}\n"
+ "}\n"
},
@@ -1697,32 +1865,32 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
"1. WARNING in X.java (at line 4)\n" +
" return dubious;\n" +
" ^^^^^^^\n" +
- "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'String []\'\n" +
+ "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'@NonNull String []\'\n" +
"----------\n" +
"2. WARNING in X.java (at line 7)\n" +
" return dubious;\n" +
" ^^^^^^^\n" +
- "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'String []\'\n" +
+ "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'@Nullable String []\'\n" +
"----------\n" +
"3. WARNING in X.java (at line 10)\n" +
" @Nullable String[] l1 = dubious;\n" +
" ^^^^^^^\n" +
- "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'String []\'\n" +
+ "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'@Nullable String []\'\n" +
"----------\n" +
"4. WARNING in X.java (at line 11)\n" +
" @NonNull String[] l2 = dubious;\n" +
" ^^^^^^^\n" +
- "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'String []\'\n" +
+ "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'@NonNull String []\'\n" +
"----------\n" +
"5. WARNING in X.java (at line 14)\n" +
" acceptNulls(dubious);\n" +
" ^^^^^^^\n" +
- "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'String []\'\n" +
+ "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'@Nullable String []\'\n" +
"----------\n" +
"6. WARNING in X.java (at line 15)\n" +
" acceptNoNulls(dubious);\n" +
" ^^^^^^^\n" +
- "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'String []\'\n" +
+ "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'@NonNull String []\'\n" +
"----------\n");
}
@@ -1783,8 +1951,6 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
}
// types with null annotations on details (array content) are incompatible to opposite types
- // TODO(Stephan) : Per the right interpretation of the spec, @Nullable and @NonNull are annotating the component type and not the arrays. The new diagnostics are correct, but
- // should mention the annotation on the leaf type.
public void testCompatibility4a() {
runNegativeTestWithLibs(
new String[] {
@@ -1810,32 +1976,32 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
"1. ERROR in X.java (at line 4)\n" +
" return noNulls;\n" +
" ^^^^^^^\n" +
- "Null type mismatch (type annotations): required \'String []\' but this expression has type \'String []\'\n" +
+ "Null type mismatch (type annotations): required \'@Nullable String []\' but this expression has type \'@NonNull String []\'\n" +
"----------\n" +
"2. ERROR in X.java (at line 7)\n" +
" return withNulls;\n" +
" ^^^^^^^^^\n" +
- "Null type mismatch (type annotations): required \'String []\' but this expression has type \'String []\'\n" +
+ "Null type mismatch (type annotations): required \'@NonNull String []\' but this expression has type \'@Nullable String []\'\n" +
"----------\n" +
"3. ERROR in X.java (at line 10)\n" +
" @NonNull String[] l1 = withNulls;\n" +
" ^^^^^^^^^\n" +
- "Null type mismatch (type annotations): required \'String []\' but this expression has type \'String []\'\n" +
+ "Null type mismatch (type annotations): required \'@NonNull String []\' but this expression has type \'@Nullable String []\'\n" +
"----------\n" +
"4. ERROR in X.java (at line 11)\n" +
" @Nullable String[] l2 = noNulls;\n" +
" ^^^^^^^\n" +
- "Null type mismatch (type annotations): required \'String []\' but this expression has type \'String []\'\n" +
+ "Null type mismatch (type annotations): required \'@Nullable String []\' but this expression has type \'@NonNull String []\'\n" +
"----------\n" +
"5. ERROR in X.java (at line 14)\n" +
" assigns(withNulls, noNulls);\n" +
" ^^^^^^^^^\n" +
- "Null type mismatch (type annotations): required \'String []\' but this expression has type \'String []\'\n" +
+ "Null type mismatch (type annotations): required \'@NonNull String []\' but this expression has type \'@Nullable String []\'\n" +
"----------\n" +
"6. ERROR in X.java (at line 14)\n" +
" assigns(withNulls, noNulls);\n" +
" ^^^^^^^\n" +
- "Null type mismatch (type annotations): required \'String []\' but this expression has type \'String []\'\n" +
+ "Null type mismatch (type annotations): required \'@Nullable String []\' but this expression has type \'@NonNull String []\'\n" +
"----------\n");
}
@@ -2294,7 +2460,7 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
"The method foo(List<X>) of type Z should be tagged with @Override since it actually overrides a superclass method\n" +
"----------\n");
}
- // TODO(Stephan) : the message needs clean up.
+
public void testBug416175() {
runNegativeTestWithLibs(
new String[] {
@@ -2317,12 +2483,12 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
"1. WARNING in X.java (at line 8)\n" +
" List<@NonNull ? extends @NonNull String> ls = new ArrayList<String>();\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^\n" +
- "Null type safety (type annotations): The expression of type \'ArrayList<String>\' needs unchecked conversion to conform to \'List<@NonNull ? extends java.lang.String>\'\n" +
+ "Null type safety (type annotations): The expression of type \'ArrayList<String>\' needs unchecked conversion to conform to \'List<@NonNull ? extends String>\'\n" +
"----------\n" +
"2. ERROR in X.java (at line 9)\n" +
" ls.add(null);\n" +
" ^^^^\n" +
- "Null type mismatch: required \'@NonNull capture#\' but the provided value is null\n" +
+ "Null type mismatch: required \'@NonNull ? extends String\' but the provided value is null\n" +
"----------\n");
}
@@ -2358,9 +2524,16 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
" @NonNull T bar1(@NonNull T t) {\n" +
" return t;\n" +
" }\n" +
- " @NonNull T bar2(@Nullable T t) { // contradiction: cannot make T @Nullable\n" +
+ " @NonNull T bar2(@Nullable T t) { // argument: contradiction (1)\n" +
" return t;\n" +
" }\n" +
+ " @Nullable T bar3(T t) { // return type: contradiction (2)\n" +
+ " @Nullable T l = t; // local: contradiction (3)\n" +
+ " return l;\n" +
+ " }\n" +
+ " class Inner {\n" +
+ " @Nullable T f; // field: contradiction (4)\n" +
+ " }\n" +
" T bar3() {\n" +
" return null;\n" +
" }\n" +
@@ -2369,11 +2542,26 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
getCompilerOptions(),
"----------\n" +
"1. ERROR in X.java (at line 11)\n" +
- " @NonNull T bar2(@Nullable T t) { // contradiction: cannot make T @Nullable\n" +
+ " @NonNull T bar2(@Nullable T t) { // argument: contradiction (1)\n" +
" ^^^^^^^^^\n" +
"Contradictory null specification; only one of @NonNull and @Nullable can be specified at any location\n" +
"----------\n" +
- "2. ERROR in X.java (at line 15)\n" +
+ "2. ERROR in X.java (at line 14)\n" +
+ " @Nullable T bar3(T t) { // return type: contradiction (2)\n" +
+ " ^^^^^^^^^\n" +
+ "Contradictory null specification; only one of @NonNull and @Nullable can be specified at any location\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 15)\n" +
+ " @Nullable T l = t; // local: contradiction (3)\n" +
+ " ^^^^^^^^^\n" +
+ "Contradictory null specification; only one of @NonNull and @Nullable can be specified at any location\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 19)\n" +
+ " @Nullable T f; // field: contradiction (4)\n" +
+ " ^^^^^^^^^\n" +
+ "Contradictory null specification; only one of @NonNull and @Nullable can be specified at any location\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 22)\n" +
" return null;\n" +
" ^^^^\n" +
"Null type mismatch: required \'@NonNull T\' but the provided value is null\n" +
@@ -2468,7 +2656,7 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
"----------\n");
}
- public void testBug416182() {
+ public void testBug416182() {
runNegativeTestWithLibs(
new String[] {
"X.java",
@@ -2480,7 +2668,7 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
" return t;\n" +
" }\n" +
" public static void main(String[] args) {\n" +
- " X<@Nullable String> xs = new X<String>();\n" +
+ " X<@Nullable String> xs = new X<String>();\n" + // TODO(stephan): must detect that foo() now has contradictory annots, see bug 416190
" xs.foo(null);\n" +
" }\n" +
" \n" +
@@ -2499,12 +2687,7 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
" ^^^^^^^^^^^^^^^\n" +
"Null type safety (type annotations): The expression of type 'X<String>' needs unchecked conversion to conform to 'X<@Nullable String>'\n" +
"----------\n" +
- "2. ERROR in X.java (at line 10)\n" +
- " xs.foo(null);\n" +
- " ^^^^\n" +
- "Null type mismatch: required '@NonNull String' but the provided value is null\n" +
- "----------\n" +
- "3. WARNING in X.java (at line 14)\n" +
+ "2. WARNING in X.java (at line 14)\n" +
" X<@Nullable String> xs = x;\n" +
" ^\n" +
"Null type safety (type annotations): The expression of type \'X<String>\' needs unchecked conversion to conform to \'X<@Nullable String>\'\n" +
@@ -2531,4 +2714,509 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest {
getCompilerOptions(),
"");
}
+ // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=417113#c25, point 4.
+ public void testSubstitution() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "import java.util.List;\n" +
+ "import java.util.ArrayList;\n" +
+ "public class X<T> {\n" +
+ " T foo(@NonNull List<@NonNull T> l) {\n" +
+ " return l.get(0);\n" +
+ " } \n" +
+ " public static void main(String[] args) {\n" +
+ " X<String> s = new X<>();\n" +
+ " s.foo(new ArrayList<String>()); // (1)\n" +
+ " s.foo(null); // (2)\n" +
+ " }\n" +
+ "}\n"
+
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. WARNING in X.java (at line 10)\n" +
+ " s.foo(new ArrayList<String>()); // (1)\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Null type safety (type annotations): The expression of type \'ArrayList<String>\' needs unchecked conversion to conform to \'@NonNull List<@NonNull String>\'\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 11)\n" +
+ " s.foo(null); // (2)\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull List<@NonNull String>\' but the provided value is null\n" +
+ "----------\n");
+ }
+ // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=417113#c25, point 4.
+ public void testSubstitution2() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "public class X<T> {\n" +
+ " T foo(@NonNull T @NonNull [] l) {\n" +
+ " return l[0];\n" +
+ " } \n" +
+ " public static void main(String[] args) {\n" +
+ " X<String> s = new X<>();\n" +
+ " s.foo(new String [] { null });\n" +
+ " s.foo(new String @Nullable [] { null });\n" +
+ " s.foo(new String @NonNull [] { null });\n" +
+ " s.foo(new @Nullable String @NonNull [] { null });\n" +
+ " s.foo(new @NonNull String @NonNull [] { \"\" });\n" +
+ " s.foo(null); // (2)\n" +
+ " }\n" +
+ "}\n"
+
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. WARNING in X.java (at line 9)\n" +
+ " s.foo(new String [] { null });\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Null type safety (type annotations): The expression of type \'String[]\' needs unchecked conversion to conform to \'@NonNull String @NonNull[]\'\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 10)\n" +
+ " s.foo(new String @Nullable [] { null });\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Null type safety (type annotations): The expression of type \'String @Nullable[]\' needs unchecked conversion to conform to \'@NonNull String @NonNull[]\'\n" +
+ "----------\n" +
+ "3. WARNING in X.java (at line 11)\n" +
+ " s.foo(new String @NonNull [] { null });\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Null type safety (type annotations): The expression of type \'String @NonNull[]\' needs unchecked conversion to conform to \'@NonNull String @NonNull[]\'\n" +
+ "----------\n" +
+ "4. ERROR in X.java (at line 12)\n" +
+ " s.foo(new @Nullable String @NonNull [] { null });\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Null type mismatch (type annotations): required \'@NonNull String @NonNull[]\' but this expression has type \'@Nullable String @NonNull[]\'\n" +
+ "----------\n" +
+ "5. ERROR in X.java (at line 14)\n" +
+ " s.foo(null); // (2)\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String @NonNull[]\' but the provided value is null\n" +
+ "----------\n");
+ }
+ // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=417113#c25, point 4.
+ public void testSubstitution3() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "public class X<T> {\n" +
+ " T foo(@NonNull T l) {\n" +
+ " return l;\n" +
+ " } \n" +
+ " public static void main(String[] args) {\n" +
+ " X<String> s = new X<>();\n" +
+ " s.foo(null);\n" +
+ " }\n" +
+ "}\n"
+
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " s.foo(null);\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String\' but the provided value is null\n" +
+ "----------\n");
+ }
+ // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=417113#c25, point 4.
+ public void testSubstitution4() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface TypeAnnotation {\n" +
+ "}\n" +
+ "public class X<T> {\n" +
+ " class Y {}\n" +
+ " void foo(@TypeAnnotation X<T>.@NonNull Y l) {\n" +
+ " } \n" +
+ " public static void main(String[] args) {\n" +
+ " X<String> s = new X<>();\n" +
+ " s.foo(null);\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in X.java (at line 13)\n" +
+ " s.foo(null);\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'X<String>.@NonNull Y\' but the provided value is null\n" +
+ "----------\n");
+ }
+ // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=417113#c25, point 4.
+ public void testSubstitution5() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "public class X<T> {\n" +
+ " void foo(@NonNull X<@NonNull ? extends T> p) {\n" +
+ " } \n" +
+ " public static void main(String[] args) {\n" +
+ " X<String> s = new X<>();\n" +
+ " X<@NonNull String> s2 = new X<@NonNull String>();\n" +
+ " s.foo(s);\n" +
+ " s.foo(s2);\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. WARNING in X.java (at line 8)\n" +
+ " s.foo(s);\n" +
+ " ^\n" +
+ "Null type safety (type annotations): The expression of type \'X<String>\' needs unchecked conversion to conform to \'@NonNull X<@NonNull ? extends String>\'\n" +
+ "----------\n");
+ }
+
+ // https://bugs.eclipse.org/417758 - [1.8][null] Null safety compromise during array creation.
+ // original test case
+ public void testArray1() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "\n" +
+ "public class X<T> {\n" +
+ " \n" +
+ " public static void main(String[] args) {\n" +
+ " @NonNull String @NonNull [] s = new @NonNull String [] { null };\n" +
+ " if (s != null && s[0] != null) {\n" +
+ " System.out.println(\"Not null\");\n" +
+ " }\n" +
+ " System.out.println(\"Length = \" + s[0].length());\n" +
+ " }\n" +
+ "}"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " @NonNull String @NonNull [] s = new @NonNull String [] { null };\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String\' but the provided value is null\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 7)\n" +
+ " if (s != null && s[0] != null) {\n" +
+ " ^\n" +
+ "Redundant null check: comparing \'@NonNull String @NonNull[]\' against null\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 7)\n" +
+ " if (s != null && s[0] != null) {\n" +
+ " ^^^^\n" +
+ "Redundant null check: comparing \'@NonNull String\' against null\n" +
+ "----------\n");
+ }
+
+ // https://bugs.eclipse.org/417758 - [1.8][null] Null safety compromise during array creation.
+ // two-dim array with annotations on dimensions
+ public void testArray2() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "\n" +
+ "public class X<T> {\n" +
+ " \n" +
+ " public static void main(String[] args) {\n" +
+ " @NonNull String @NonNull [][] s1 = new @NonNull String @NonNull [][] { null, { null} }; // problem at inner null\n" +
+ " @NonNull String @NonNull [][] s2 = new @NonNull String [] @NonNull [] { null, { null} }; // problem at both nulls\n" +
+ " }\n" +
+ "}"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in X.java (at line 6)\n" +
+ " @NonNull String @NonNull [][] s1 = new @NonNull String @NonNull [][] { null, { null} }; // problem at inner null\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String\' but the provided value is null\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 7)\n" +
+ " @NonNull String @NonNull [][] s2 = new @NonNull String [] @NonNull [] { null, { null} }; // problem at both nulls\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String @NonNull[]\' but the provided value is null\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 7)\n" +
+ " @NonNull String @NonNull [][] s2 = new @NonNull String [] @NonNull [] { null, { null} }; // problem at both nulls\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String\' but the provided value is null\n" +
+ "----------\n");
+ }
+
+ // https://bugs.eclipse.org/417758 - [1.8][null] Null safety compromise during array creation.
+ // three-dim array with annotations on dimensions, also assignment has a problem
+ public void testArray3() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "\n" +
+ "public class X<T> {\n" +
+ " \n" +
+ " public static void main(String[] args) {\n" +
+ " @NonNull String [][] @NonNull [] s = new @NonNull String []@NonNull [][] { null, { {null}, null/*ok*/ } };\n" +
+ " }\n" +
+ "}"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. WARNING in X.java (at line 6)\n" +
+ " @NonNull String [][] @NonNull [] s = new @NonNull String []@NonNull [][] { null, { {null}, null/*ok*/ } };\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Null type safety (type annotations): The expression of type \'@NonNull String [] @NonNull[] []\' needs unchecked conversion to conform to \'@NonNull String [] [] @NonNull[]\'\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 6)\n" +
+ " @NonNull String [][] @NonNull [] s = new @NonNull String []@NonNull [][] { null, { {null}, null/*ok*/ } };\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String @NonNull[] []\' but the provided value is null\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 6)\n" +
+ " @NonNull String [][] @NonNull [] s = new @NonNull String []@NonNull [][] { null, { {null}, null/*ok*/ } };\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull String\' but the provided value is null\n" +
+ "----------\n");
+ }
+
+ public void testBug417759() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import org.eclipse.jdt.annotation.*;\n" +
+ "\n" +
+ "public class X<T> {\n" +
+ " void foo(@NonNull X<@NonNull ?> l) { \n" +
+ " } \n" +
+ " public static void main(String[] args) {\n" +
+ " @NonNull X<String> s = new X<>();\n" +
+ " s.foo(s); // String vs. @NonNull ?\n" +
+ " @NonNull X<@Nullable String> s2 = new X<>();\n" +
+ " s.foo(s2); // @Nullable String vs. @NonNull ?\n" +
+ " @NonNull X<@NonNull String> s3 = new X<>();\n" +
+ " s.foo(s3); // good\n" +
+ " }\n" +
+ "}"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. WARNING in X.java (at line 8)\n" +
+ " s.foo(s); // String vs. @NonNull ?\n" +
+ " ^\n" +
+ "Null type safety (type annotations): The expression of type \'@NonNull X<String>\' needs unchecked conversion to conform to \'@NonNull X<@NonNull ?>\'\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 10)\n" +
+ " s.foo(s2); // @Nullable String vs. @NonNull ?\n" +
+ " ^^\n" +
+ "Null type mismatch (type annotations): required \'@NonNull X<@NonNull ?>\' but this expression has type \'@NonNull X<@Nullable String>\'\n" +
+ "----------\n");
+ }
+ public void testTypeVariable() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface Junk {\n" +
+ "}\n" +
+ "public class X<@NonNull T> {\n" +
+ " T t = null;\n" +
+ " @Junk T t2 = null;\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " T t = null;\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull T\' but the provided value is null\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 9)\n" +
+ " @Junk T t2 = null;\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'@NonNull T\' but the provided value is null\n" +
+ "----------\n");
+ }
+ public void testSE7AnnotationCopy() { // we were dropping annotations here, but null analysis worked already since the tagbits were not "dropped", just the same capturing in a test
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ "}\n" +
+ "public class X {\n" +
+ " class Y {}\n" +
+ " void foo(@T X.@NonNull Y p) {\n" +
+ " foo(null);\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. ERROR in X.java (at line 10)\n" +
+ " foo(null);\n" +
+ " ^^^^\n" +
+ "Null type mismatch: required \'X.@NonNull Y\' but the provided value is null\n" +
+ "----------\n");
+ }
+ public void testWildcardCapture() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "import java.util.ArrayList;\n" +
+ "import java.util.List;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ "}\n" +
+ "\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " List<X> ax = new ArrayList<X>();\n" +
+ " ax.add(new X());\n" +
+ " List<? extends X> lx = ax;\n" +
+ " getAdd(lx);\n" +
+ " }\n" +
+ " static <@NonNull P> void getAdd(List<P> lt) {\n" +
+ " lt.add(lt.get(0));\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. WARNING in X.java (at line 16)\n" +
+ " getAdd(lx);\n" +
+ " ^^\n" +
+ "Null type safety (type annotations): The expression of type \'List<capture#>\' needs unchecked conversion to conform to \'List<@NonNull capture#>\'\n" +
+ "----------\n");
+ }
+ public void testWildcardCapture2() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "import java.util.ArrayList;\n" +
+ "import java.util.List;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ "}\n" +
+ "\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " List<@NonNull X> ax = new ArrayList<@NonNull X>();\n" +
+ " ax.add(new X());\n" +
+ " List<@NonNull ? extends X> lx = ax;\n" +
+ " getAdd(lx);\n" +
+ " }\n" +
+ " static <@NonNull P> void getAdd(List<P> lt) {\n" +
+ " lt.add(lt.get(0));\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "");
+ }
+ public void testWildcardCapture3() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "import java.util.ArrayList;\n" +
+ "import java.util.List;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ "}\n" +
+ "\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " List<@Nullable X> ax = new ArrayList<@Nullable X>();\n" +
+ " ax.add(new X());\n" +
+ " List<@Nullable ? extends X> lx = ax;\n" +
+ " getAdd(lx);\n" +
+ " }\n" +
+ " static <@NonNull P> void getAdd(List<P> lt) {\n" +
+ " lt.add(lt.get(0));\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "");
+ }
+ public void testLocalArrays() {
+ runNegativeTestWithLibs(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "import org.eclipse.jdt.annotation.NonNull;\n" +
+ "import org.eclipse.jdt.annotation.Nullable;\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ "}\n" +
+ "\n" +
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " class L {};\n" +
+ " L @NonNull [] @Nullable [] la = new L[5][];\n" +
+ " L @Nullable [] @NonNull [] la2 = new L[3][];\n" +
+ " la = la2;\n" +
+ " }\n" +
+ "}\n"
+ },
+ getCompilerOptions(),
+ "----------\n" +
+ "1. WARNING in X.java (at line 13)\n" +
+ " L @NonNull [] @Nullable [] la = new L[5][];\n" +
+ " ^^^^^^^^^^\n" +
+ "Null type safety (type annotations): The expression of type \'L[][]\' needs unchecked conversion to conform to \'L @NonNull[] @Nullable[]\'\n" +
+ "----------\n" +
+ "2. WARNING in X.java (at line 14)\n" +
+ " L @Nullable [] @NonNull [] la2 = new L[3][];\n" +
+ " ^^^^^^^^^^\n" +
+ "Null type safety (type annotations): The expression of type \'L[][]\' needs unchecked conversion to conform to \'L @Nullable[] @NonNull[]\'\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 15)\n" +
+ " la = la2;\n" +
+ " ^^^\n" +
+ "Null type mismatch (type annotations): required \'L @NonNull[] @Nullable[]\' but this expression has type \'L @Nullable[] @NonNull[]\'\n" +
+ "----------\n");
+
+ // Without annotations.
+ runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " public static void main(String[] args) {\n" +
+ " class L {};\n" +
+ " L [] [] la = new L[5][];\n" +
+ " L [] [] la2 = new L[3][];\n" +
+ " la = la2;\n" +
+ " System.out.println(\"Done\");\n" +
+ " }\n" +
+ "}\n"
+ },
+ "Done");
+ }
} \ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RepeatableAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RepeatableAnnotationTest.java
new file mode 100644
index 000000000..7ad230340
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RepeatableAnnotationTest.java
@@ -0,0 +1,840 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Jesper S Moller 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:
+ * Jesper S Moller - initial API and implementation
+ * Bug 412151 - [1.8][compiler] Check repeating annotation's collection type
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import junit.framework.Test;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.impl.IntConstant;
+import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
+
+public class RepeatableAnnotationTest extends AbstractComparableTest {
+
+ // Static initializer to specify tests subset using TESTS_* static variables
+ // All specified tests which do not belong to the class are skipped...
+ static {
+// TESTS_NAMES = new String[] { "test006" };
+// TESTS_NUMBERS = new int[] { 297 };
+// TESTS_RANGE = new int[] { 294, -1 };
+ }
+
+ public RepeatableAnnotationTest(String name) {
+ super(name);
+ }
+
+ public static Test suite() {
+ return buildMinimalComplianceTestSuite(testClass(), F_1_8);
+ }
+
+ public static Class testClass() {
+ return RepeatableAnnotationTest.class;
+ }
+
+ // check repeated occurrence of non-repeatable annotation
+ public void test001() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "public @Foo @Foo class X {\n" +
+ "}\n" +
+ "\n",
+ "Foo.java",
+ "public @interface Foo {\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 1)\n" +
+ " public @Foo @Foo class X {\n" +
+ " ^^^^\n" +
+ "Duplicate annotation of non-repeatable type @Foo. Only annotation types marked @Repeatable can be used multiple times at one target.\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 1)\n" +
+ " public @Foo @Foo class X {\n" +
+ " ^^^^\n" +
+ "Duplicate annotation of non-repeatable type @Foo. Only annotation types marked @Repeatable can be used multiple times at one target.\n" +
+ "----------\n");
+ }
+
+ public void test002() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "@Foo @Foo public class X {\n" +
+ "}\n" +
+ "\n",
+ "Foo.java",
+ "@java.lang.annotation.Repeatable(FooContainer.class) public @interface Foo {\n" +
+ "}\n",
+ "FooContainer.java",
+ "public @interface FooContainer {\n" +
+ " Foo[] value();\n" +
+ "}\n"
+ },
+ "");
+ }
+
+ // check repeated occurrence of annotation where annotation container is not valid for the target
+ public void test003() {
+ this.runNegativeTest(
+ new String[] {
+ "FooContainer.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "@Target({ElementType.METHOD, ElementType.FIELD}) public @interface FooContainer {\n" +
+
+ " Foo[] value();\n" +
+ "}\n",
+ "Foo.java",
+ "@java.lang.annotation.Repeatable(FooContainer.class) public @interface Foo {\n" +
+ "}\n",
+ "X.java",
+ "@Foo @Foo public class X { /* Problem */\n" +
+ " @Foo @Foo void okHere() { /* No problem */\n" +
+ " @Foo @Foo int local = 0; /* Problem! */\n" +
+ " }\n" +
+ " @Foo @Foo int alsoFoo = 0; /* No problem */\n" +
+ " @Foo class Y {} /* No problem since not repeated */\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 1)\n" +
+ " @Foo @Foo public class X { /* Problem */\n" +
+ " ^^^^\n" +
+ "The repeatable annotation @Foo is disallowed for this location since its container annotation @FooContainer is disallowed at this location\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 3)\n" +
+ " @Foo @Foo int local = 0; /* Problem! */\n" +
+ " ^^^^\n" +
+ "The repeatable annotation @Foo is disallowed for this location since its container annotation @FooContainer is disallowed at this location\n" +
+ "----------\n");
+ }
+
+ // This is the same test as test003, only where the annotation info for Foo is from a class file, not from the compiler
+ public void test004() {
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "@Target({ElementType.METHOD, ElementType.FIELD}) public @interface FooContainer {\n" +
+ " Foo[] value();\n" +
+ "}\n",
+ "Foo.java",
+ "@java.lang.annotation.Repeatable(FooContainer.class) public @interface Foo {\n" +
+ "}\n"
+ },
+ "");
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "@Foo @Foo public class X { /* Problem */\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 1)\n" +
+ " @Foo @Foo public class X { /* Problem */\n" +
+ " ^^^^\n" +
+ "The repeatable annotation @Foo is disallowed for this location since its container annotation @FooContainer is disallowed at this location\n" +
+ "----------\n",
+ null, false /* don't flush*/);
+ }
+
+ // Test that a single, repeatable annotation can exist just fine an occurrence of its container annotation
+ public void test005() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "@java.lang.annotation.Repeatable(FooContainer.class) @interface Foo {}\n" +
+ "@interface FooContainer { Foo[] value(); }\n" +
+ "@Foo @FooContainer({@Foo, @Foo}) public class X { /* Not a problem */ }\n"
+ },
+ "");
+ }
+
+ // Test that an repeated annotation can't occur together with its container annotation
+ public void test006() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "@interface FooContainer { Foo[] value(); }\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class) @interface Foo {}\n" +
+ "@Foo @Foo @FooContainer({@Foo, @Foo}) public class X { /* A problem */ }\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 3)\n" +
+ " @Foo @Foo @FooContainer({@Foo, @Foo}) public class X { /* A problem */ }\n" +
+ " ^^^^\n" +
+ "The repeatable annotation @Foo may not be repeated where its container annotation @FooContainer is also used directly\n" +
+ "----------\n");
+ }
+
+ // Test that an repeated annotation can't occur together with its container annotation, even if it itself is repeatable.
+ public void test007() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "@interface FooContainerContainer { FooContainer[] value(); }\n" +
+ "@java.lang.annotation.Repeatable(FooContainerContainer.class) @interface FooContainer { Foo[] value(); }\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class) @interface Foo {}\n" +
+ "@Foo @Foo @FooContainer({@Foo, @Foo}) public class X { /* Still a problem */ }\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " @Foo @Foo @FooContainer({@Foo, @Foo}) public class X { /* Still a problem */ }\n" +
+ " ^^^^\n" +
+ "The repeatable annotation @Foo may not be repeated where its container annotation @FooContainer is also used directly\n" +
+ "----------\n");
+ }
+
+ // Test that an repeated annotation can't occur together with its container annotation, even if it itself is repeatable.
+ public void test007a() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "@interface FooContainerContainer { FooContainer[] value(); }\n" +
+ "@java.lang.annotation.Repeatable(FooContainerContainer.class) @interface FooContainer { Foo[] value(); }\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class) @interface Foo {}\n" +
+ "@interface Bar {}\n" +
+ "@Foo @Foo @Bar @Bar @FooContainer({@Foo, @Foo}) public class X { /* Still a problem */ }\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 5)\n" +
+ " @Foo @Foo @Bar @Bar @FooContainer({@Foo, @Foo}) public class X { /* Still a problem */ }\n" +
+ " ^^^^\n" +
+ "The repeatable annotation @Foo may not be repeated where its container annotation @FooContainer is also used directly\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 5)\n" +
+ " @Foo @Foo @Bar @Bar @FooContainer({@Foo, @Foo}) public class X { /* Still a problem */ }\n" +
+ " ^^^^\n" +
+ "Duplicate annotation of non-repeatable type @Bar. Only annotation types marked @Repeatable can be used multiple times at one target.\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 5)\n" +
+ " @Foo @Foo @Bar @Bar @FooContainer({@Foo, @Foo}) public class X { /* Still a problem */ }\n" +
+ " ^^^^\n" +
+ "Duplicate annotation of non-repeatable type @Bar. Only annotation types marked @Repeatable can be used multiple times at one target.\n" +
+ "----------\n");
+ }
+
+ // Test that repeated annotations should be contiguous (raises a warning if not) -- not yet in BETA_JAVA8
+ public void _test008() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "@interface Bar {}\n" +
+ "@interface Baz {}\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class) @interface Foo {}\n" +
+ "@interface FooContainer { Foo[] value(); }\n" +
+ "@Foo @Bar @Foo /* just lexical */ @Foo public class X { /* Gives a warning */ }\n"
+ },
+ "----------\n" +
+ "1. WARNING in X.java (at line 5)\n" +
+ " @Foo @Bar @Foo /* just lexical */ @Foo public class X { /* Gives a warning */ }\n" +
+ " ^^^^\n" +
+ "Repeated @Foo annotations are not grouped together\n" +
+ "----------\n");
+ }
+ // Test that deprecation of container annotation is reflected in the repeated annotation (disabled until specification clarification is available)
+ public void _test009() {
+ this.runConformTest(
+ new String[] {
+ "Y.java",
+ "@java.lang.annotation.Repeatable(FooContainer.class) @interface Foo { int value(); }\n" +
+ "@Deprecated @interface FooContainer { Foo[] value(); }\n" +
+ "@Foo(0) class X { /* Gives a warning */ }\n" +
+ "@Foo(1) @Foo(2) public class Y { /* Gives a warning */ }\n"
+ },
+ new ASTVisitor() {
+ public boolean visit(
+ TypeDeclaration typeDeclaration,
+ CompilationUnitScope scope) {
+ if (new String(typeDeclaration.name).equals("X")) {
+ assertFalse("Foo on X should NOT be deprecated!", typeDeclaration.annotations[0].getCompilerAnnotation().getAnnotationType().isDeprecated());
+ }
+ if (new String(typeDeclaration.name).equals("Y")) {
+ assertEquals("Find Foo(1) on Y", IntConstant.fromValue(1), typeDeclaration.annotations[0].getCompilerAnnotation().getElementValuePairs()[0].value);
+ assertTrue("1st Foo on Y should be deprecated!", typeDeclaration.annotations[0].getCompilerAnnotation().getAnnotationType().isDeprecated());
+ assertEquals("Find Foo(2) on Y", IntConstant.fromValue(2), typeDeclaration.annotations[1].getCompilerAnnotation().getElementValuePairs()[0].value);
+ assertTrue("2nd Foo on Y should be deprecated!", typeDeclaration.annotations[1].getCompilerAnnotation().getAnnotationType().isDeprecated());
+ }
+ return true; // do nothing by default, keep traversing
+ }
+ });
+ }
+ // Bug 412151: [1.8][compiler] Check repeating annotation's collection type
+ // 412151: The collections type's (TC) declaration must have a array of Ts as its value() - with Foo and FooContainer in same compilation round
+ public void test010() {
+ this.runNegativeTest(
+ new String[] {
+ "Foo.java",
+ "@interface FooContainer {\n" +
+ "}\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@interface Foo {}\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 3)\n" +
+ " @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "The containing annotation @FooContainer must declare a member value()\n" +
+ "----------\n");
+ }
+ // 412151: The collections type's (TC) declaration must have a array of Ts as its value() - with Foo and FooContainer in same compilation round
+ public void test011() {
+ this.runNegativeTest(
+ new String[] {
+ "Foo.java",
+ "@interface FooContainer {\n" +
+ " int[] value();\n" +
+ "}\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@interface Foo {}\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 4)\n" +
+ " @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "The value method in the containing annotation @FooContainer must be of type Foo[] but is int[]\n" +
+ "----------\n");
+ }
+ // 412151: The collections type's (TC) declaration must have a array of Ts as its value() - with Foo and FooContainer in same compilation round
+ public void test012() {
+ this.runNegativeTest(
+ new String[] {
+ "Foo.java",
+ "@interface FooContainer {\n" +
+ " Foo[][] value();\n" +
+ "}\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@interface Foo {}\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 2)\n" +
+ " Foo[][] value();\n" +
+ " ^^^^^^^\n" +
+ "Invalid type Foo[][] for the annotation attribute FooContainer.value; only primitive type, String, Class, annotation, enumeration are permitted or 1-dimensional arrays thereof\n" +
+ "----------\n" +
+ "2. ERROR in Foo.java (at line 4)\n" +
+ " @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "The value method in the containing annotation @FooContainer must be of type Foo[] but is Foo[][]\n" +
+ "----------\n"
+ );
+ }
+ // 412151: Any methods declared by TC other than value() have a default value (�9.6.2).
+ public void test013() {
+ this.runNegativeTest(
+ new String[] {
+ "Foo.java",
+ "@interface FooContainer {\n" +
+ " Foo[] value();\n" +
+ " int hasDefaultValue() default 1337;\n" +
+ " int doesntHaveDefaultValue();\n" +
+ "}\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@interface Foo {}\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 6)\n" +
+ " @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "The containing annotation @FooContainer must declare a default value for the annotation attribute \'doesntHaveDefaultValue\'\n" +
+ "----------\n");
+ }
+ // 412151: The @Retention meta-annotation of TC must at least include the retention of T ()
+ public void test014() {
+ this.runConformTest(
+ new String[] {
+ "Foo.java",
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "@Retention(RetentionPolicy.CLASS)\n" +
+ "@interface FooContainer {\n" +
+ " Foo[] value();\n" +
+ "}\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@Retention(RetentionPolicy.CLASS)\n" +
+ "@interface Foo {\n" +
+ "}\n"
+ },
+ "");
+ }
+
+ //
+ public void test015() {
+ // These are fine:
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "public @interface FooContainer {\n" +
+ " Foo[] value();\n" +
+ "}\n",
+ "Foo.java",
+ "@java.lang.annotation.Repeatable(FooContainer.class) public @interface Foo {\n" +
+ "}\n"
+ },
+ "");
+ // This changes FooContainer without re-checking Foo
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "public @interface FooContainer {\n" +
+ " int[] value();\n" +
+ "}\n"
+ },
+ "",
+ null,
+ false,
+ null);
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "@Foo @Foo public class X { /* Problem since Foo now uses FooContainer which doesn't work anymore*/\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 1)\n" +
+ " @Foo @Foo public class X { /* Problem since Foo now uses FooContainer which doesn\'t work anymore*/\n" +
+ " ^^^^\n" +
+ "The value method in the containing annotation @FooContainer must be of type Foo[] but is int[]\n" +
+ "----------\n",
+ null, false /* don't flush*/);
+ }
+
+ // 412151: The @Retention meta-annotation of TC must at least include the retention of T ()
+ // Base example, both targets are specified
+ public void test016() {
+ this.runNegativeTest(
+ new String[] {
+ "Foo.java",
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "@Retention(RetentionPolicy.SOURCE)\n" +
+ "@interface FooContainer { Foo[] value(); }\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface Foo { }\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 5)\n" +
+ " @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "Retention \'RUNTIME\' of @Foo is longer than the retention of the containing annotation @FooContainer, which is \'SOURCE\'\n" +
+ "----------\n");
+ }
+
+ // 412151: The @Retention meta-annotation of TC must at least include the retention of T ()
+ // Only specified on FooContainer
+ public void test017() {
+ this.runNegativeTest(
+ new String[] {
+ "Foo.java",
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "@Retention(RetentionPolicy.SOURCE)\n" +
+ "@interface FooContainer { Foo[] value(); }\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@interface Foo { }\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 5)\n" +
+ " @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "Retention \'CLASS\' of @Foo is longer than the retention of the containing annotation @FooContainer, which is \'SOURCE\'\n" +
+ "----------\n");
+ }
+
+ // 412151: The @Retention meta-annotation of TC must at least include the retention of T ()
+ // Only specified on Foo
+ public void test018() {
+ this.runNegativeTest(
+ new String[] {
+ "Foo.java",
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "@interface FooContainer { Foo[] value(); }\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface Foo { }\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 4)\n" +
+ " @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "Retention \'RUNTIME\' of @Foo is longer than the retention of the containing annotation @FooContainer, which is \'CLASS\'\n" +
+ "----------\n");
+ }
+
+ // 412151: The @Retention meta-annotation of TC must at least include the retention of T ()
+ // Only specified on Foo - but positive
+ public void test019() {
+ this.runConformTest(
+ new String[] {
+ "Foo.java",
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "@interface FooContainer { Foo[] value(); }\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@Retention(RetentionPolicy.SOURCE)\n" +
+ "@interface Foo { }\n"
+ });
+ }
+
+ // 412151: The @Retention meta-annotation of TC must at least include the retention of T
+ // Only specified on FooContainer, separate compilation
+ public void test020() {
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "@Retention(RetentionPolicy.SOURCE)\n" +
+ "public @interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "@Retention(RetentionPolicy.SOURCE)\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "public @interface Foo { }\n"
+ });
+ this.runNegativeTest(
+ new String[] {
+ "Foo.java",
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "public @interface Foo { } // If omitted, retention is class\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 1)\n" +
+ " @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "Retention \'CLASS\' of @Foo is longer than the retention of the containing annotation @FooContainer, which is \'SOURCE\'\n" +
+ "----------\n",
+ null, false /* don't flush*/);
+ }
+
+ // 412151: The @Retention meta-annotation of TC must at least include the retention of T ()
+ // Only specified on Foo, separate compilation
+ public void test021() {
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "public @interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "public @interface Foo { }\n"
+ });
+ this.runNegativeTest(
+ new String[] {
+ "Foo.java",
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface Foo { }\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 3)\n" +
+ " @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "Retention \'RUNTIME\' of @Foo is longer than the retention of the containing annotation @FooContainer, which is \'CLASS\'\n" +
+ "----------\n",
+ null, false /* don't flush*/);
+ }
+
+ // 412151: TC's @Targets, if specified, must be a subset or the same as T's @Targets
+ // TC's @Targets, if specified, must be a subset or the same as T's @Targets. Simple test
+ public void test022() {
+ this.runNegativeTest(
+ new String[] {
+ "FooContainer.java",
+ "import java.lang.annotation.Target;\n" +
+ "import java.lang.annotation.ElementType;\n" +
+ "public @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})\n" +
+ "@interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "import java.lang.annotation.Target;\n" +
+ "import java.lang.annotation.ElementType;\n" +
+ "public @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@Target({ElementType.FIELD})\n" +
+ "@interface Foo { }\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 3)\n" +
+ " public @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "The containing annotation @FooContainer is allowed at targets where the repeatable annotation @Foo is not: TYPE, METHOD\n" +
+ "----------\n");
+ }
+
+ // 412151: TC's @Targets, if specified, must be a subset or the same as T's @Targets
+ // TC's @Targets, if specified, must be a subset or the same as T's @Targets. Test this as a separate pass, so that
+ // FooContainer is loaded from binary.
+ public void test023() {
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "import java.lang.annotation.Target;\n" +
+ "import java.lang.annotation.ElementType;\n" +
+ "public @Target({ElementType.METHOD})\n" +
+ "@interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "import java.lang.annotation.Target;\n" +
+ "import java.lang.annotation.ElementType;\n" +
+ "public @Target({ElementType.METHOD})\n" +
+ "@interface Foo { }\n"
+ });
+ this.runNegativeTest(
+ new String[] {
+ "Foo.java",
+ "import java.lang.annotation.Target;\n" +
+ "import java.lang.annotation.ElementType;\n" +
+ "public @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@java.lang.annotation.Target({ElementType.FIELD})\n" +
+ "@interface Foo { }\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 3)\n" +
+ " public @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "The containing annotation @FooContainer is allowed at targets where the repeatable annotation @Foo is not: METHOD\n" +
+ "----------\n",
+ null, false /* don't flush*/);
+ }
+
+ // 412151: TC's @Targets, if specified, must be a subset or the same as T's @Targets
+ // TC's may target ANNOTATION_TYPE but that should match TYPE for T, since it's a superset
+ public void test024() {
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "@java.lang.annotation.Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})\n" +
+ "@interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@java.lang.annotation.Target({ElementType.METHOD, ElementType.TYPE})\n" +
+ "@interface Foo { }\n"
+ });
+ }
+
+ // 412151: TC's @Targets, if specified, must be a subset or the same as T's @Targets
+ // Test that all ElementTypes can be reported
+ public void test025() {
+ this.runNegativeTest(
+ new String[] {
+ "FooContainer.java",
+ "import java.lang.annotation.Target;\n" +
+ "import java.lang.annotation.ElementType;\n" +
+ "public @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE, ElementType.ANNOTATION_TYPE, ElementType.PACKAGE, ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})\n" +
+ "@interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "import java.lang.annotation.Target;\n" +
+ "import java.lang.annotation.ElementType;\n" +
+ "public @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@Target({})\n" +
+ "@interface Foo { }\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 3)\n" +
+ " public @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "The containing annotation @FooContainer is allowed at targets where the repeatable annotation @Foo is not: TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER, TYPE_USE\n" +
+ "----------\n");
+ }
+
+ // 412151: TC's @Targets, if specified, must be a subset or the same as T's @Targets
+ // TC's has no @Targets (=everywhere), but @Foo has, then complain.
+ public void test026() {
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "@interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "@interface Foo { }\n"
+ });
+ this.runNegativeTest(
+ new String[] {
+ "Foo.java",
+ "import java.lang.annotation.Target;\n" +
+ "import java.lang.annotation.ElementType;\n" +
+ "@java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@java.lang.annotation.Target({ElementType.FIELD})\n" +
+ "@interface Foo { }\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 3)\n" +
+ " @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "The repeatable annotation @Foo has a @Target annotation, @FooContainer does not\n" +
+ "----------\n",
+ null, false /* don't flush*/);
+ }
+
+ // 412151: If T is @Documented, then TC should also be Documented
+ public void test027() {
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "@java.lang.annotation.Documented @interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "@java.lang.annotation.Documented @interface Foo { }\n"});
+ }
+
+ // 412151: If T is @Documented, then TC should also be Documented, OK for TC to be documented while T is not
+ public void test028() {
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "@java.lang.annotation.Documented @interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "@interface Foo { }\n"});
+ }
+
+ // 412151: If T is @Documented, then TC should also be Documented
+ public void test029() {
+ this.runNegativeTest(
+ new String[] {
+ "FooContainer.java",
+ "@interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "@java.lang.annotation.Repeatable(FooContainer.class) @java.lang.annotation.Documented\n" +
+ "@interface Foo { }\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 1)\n" +
+ " @java.lang.annotation.Repeatable(FooContainer.class) @java.lang.annotation.Documented\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "The repeatable annotation @Foo is marked @Documented, but the containing annotation @FooContainer is not\n" +
+ "----------\n");
+ }
+
+ // 412151: If T is @Documented, then TC should also be Documented - check from previous compilation
+ public void test030() {
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "@java.lang.annotation.Documented @interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "@java.lang.annotation.Documented @interface Foo { }\n"
+ });
+ this.runConformTest(
+ new String[] {
+ "Foo.java",
+ "public @java.lang.annotation.Documented @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@interface Foo { }\n"
+ },
+ "",
+ null,
+ false,
+ null);
+ }
+
+ // 412151: If T is @Inherited, then TC should also be Inherited
+ public void test031() {
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "@java.lang.annotation.Inherited @interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "@java.lang.annotation.Inherited @interface Foo { }\n"});
+ }
+
+ // 412151: If T is @Inherited, then TC should also be Inherited, OK for TC to be inherited while T is not.
+ public void test032() {
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "@java.lang.annotation.Inherited @interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "@interface Foo { }\n"});
+ }
+ // 412151: If T is @Inherited, then TC should also be Inherited
+ public void test033() {
+ this.runNegativeTest(
+ new String[] {
+ "FooContainer.java",
+ "@interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "@java.lang.annotation.Repeatable(FooContainer.class) @java.lang.annotation.Inherited\n" +
+ "@interface Foo { }\n"
+ },
+ "----------\n" +
+ "1. ERROR in Foo.java (at line 1)\n" +
+ " @java.lang.annotation.Repeatable(FooContainer.class) @java.lang.annotation.Inherited\n" +
+ " ^^^^^^^^^^^^^^^^^^\n" +
+ "The repeatable annotation @Foo is marked @Inherited, but the containing annotation @FooContainer is not\n" +
+ "----------\n");
+ }
+
+ // 412151: If T is @Inherited, then TC should also be Inherited - check from previous compilation
+ public void test034() {
+ this.runConformTest(
+ new String[] {
+ "FooContainer.java",
+ "@java.lang.annotation.Inherited @interface FooContainer { Foo[] value(); }\n",
+ "Foo.java",
+ "@java.lang.annotation.Inherited @interface Foo { }\n"
+ });
+ this.runConformTest(
+ new String[] {
+ "Foo.java",
+ "public @java.lang.annotation.Inherited @java.lang.annotation.Repeatable(FooContainer.class)\n" +
+ "@interface Foo { }\n"
+ },
+ "",
+ null,
+ false,
+ null);
+ }
+ // 412151: Ensure no double reporting for bad target.
+ public void test035() {
+ this.runNegativeTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Repeatable;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "@Target(ElementType.FIELD)\n" +
+ "@interface TC {\n" +
+ " T [] value();\n" +
+ "}\n" +
+ "@Target(ElementType.TYPE)\n" +
+ "@Repeatable(TC.class)\n" +
+ "@interface T {\n" +
+ "}\n" +
+ "@T @T // we used to double report here.\n" +
+ "public class X { \n" +
+ " X f;\n" +
+ "}\n"
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 9)\n" +
+ " @Repeatable(TC.class)\n" +
+ " ^^^^^^^^\n" +
+ "The containing annotation @TC is allowed at targets where the repeatable annotation @T is not: FIELD\n" +
+ "----------\n" +
+ "2. ERROR in X.java (at line 12)\n" +
+ " @T @T // we used to double report here.\n" +
+ " ^^\n" +
+ "The repeatable annotation @T is disallowed for this location since its container annotation @TC is disallowed at this location\n" +
+ "----------\n");
+ }
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
index 986b47dc5..c5c27b435 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TestAll.java
@@ -20,6 +20,7 @@
* bug 407191 - [1.8] Binary access support for type annotations
* Jesper Steen Moeller - Contributions for:
* Bug 406973 - [compiler] Parse MethodParameters attribute
+ * Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
@@ -148,6 +149,7 @@ public static Test suite() {
since_1_8.add(Deprecated18Test.class);
since_1_8.add(MethodParametersAttributeTest.class);
since_1_8.add(ClassFileReaderTest_1_8.class);
+ since_1_8.add(RepeatableAnnotationTest.class);
// Build final test suite
TestSuite all = new TestSuite(TestAll.class.getName());
@@ -226,9 +228,6 @@ public static Test suite() {
tests_1_8.addAll(since_1_6);
tests_1_8.addAll(since_1_7);
tests_1_8.addAll(since_1_8);
- // TODO(stephan) temporary workaround, several tests currently fail at 1.8:
- tests_1_8.remove(NullAnnotationTest.class);
- //
// Reset forgotten subsets tests
TestCase.TESTS_PREFIX = null;
TestCase.TESTS_NAMES = null;
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java
index dd1403aba..47bd5f5c3 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TypeAnnotationTest.java
@@ -16,6 +16,7 @@
* Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator
* Bug 409246 - [1.8][compiler] Type annotations on catch parameters not handled properly
* Bug 409517 - [1.8][compiler] Type annotation problems on more elaborate array references
+ * Bug 415821 - [1.8][compiler] CLASS_EXTENDS target type annotation missing for anonymous classes
* Stephan Herrmann - Contribution for
* Bug 415911 - [1.8][compiler] NPE when TYPE_USE annotated method with missing return type
* Bug 416176 - [1.8][compiler][null] null type annotations cause grief on type variables
@@ -2531,6 +2532,65 @@ public class TypeAnnotationTest extends AbstractRegressionTest {
checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
}
+ public void test057_codeblocks_new3_415821() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.*;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface X { }\n" +
+ "\n" +
+ "class Foo {}\n",
+ "C.java",
+ "class C { void m() { new @X Foo() {}; } }\n",
+ },
+ "");
+ String expectedOutput =
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #21 @X(\n" +
+ " target type = 0x44 NEW\n" +
+ " offset = 0\n" +
+ " )\n";
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator + "C.class", "C", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #28 @X(\n" +
+ " target type = 0x10 CLASS_EXTENDS\n" +
+ " type index = -1\n" +
+ " )\n";
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator + "C$1.class", "C$1", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
+ }
+
+ public void test057_codeblocks_new4_415821() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.*;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface X { }\n" +
+ "\n",
+ "C.java",
+ "class C { void m() { new @X Runnable() { public void run() {}}; } }\n",
+ },
+ "");
+ String expectedOutput =
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #21 @X(\n" +
+ " target type = 0x44 NEW\n" +
+ " offset = 0\n" +
+ " )\n";
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator + "C.class", "C", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
+ expectedOutput =
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #31 @X(\n" +
+ " target type = 0x10 CLASS_EXTENDS\n" +
+ " type index = 0\n" +
+ " )\n";
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator + "C$1.class", "C$1", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
+ }
+
public void test059_codeblocks_new_newArray() throws Exception {
this.runConformTest(
new String[] {
@@ -5512,5 +5572,457 @@ public class TypeAnnotationTest extends AbstractRegressionTest {
"Missing cannot be resolved to a type\n" +
"----------\n");
}
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=417660, [1.8][compiler] Incorrect parsing of Annotations with array dimensions in arguments
+ public void test417660() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.Documented;\n" +
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "public class X {\n" +
+ " int bar(int [] @TakeType(int[].class)[] x) { \n" +
+ " return x[0][0]; \n" +
+ " } \n" +
+ " public static void main(String[] args) {\n" +
+ " System.out.println(new X().bar(new int [][] { { 1234 }}));\n" +
+ " }\n" +
+ "}\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@Documented\n" +
+ "@interface TakeType {\n" +
+ " Class value() default int[].class;\n" +
+ "}\n"
+ },
+ "1234");
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=417660, [1.8][compiler] Incorrect parsing of Annotations with array dimensions in arguments
+ public void test417660b() {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.Documented;\n" +
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Retention;\n" +
+ "import java.lang.annotation.RetentionPolicy;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "public class X {\n" +
+ " int bar(int [][] @TakeType(int[].class)[][] x @TakeType(int[].class)[]) { \n" +
+ " return x[0][0][0][0][0]; \n" +
+ " } \n" +
+ " public static void main(String[] args) {\n" +
+ " System.out.println(new X().bar(new int [][][][][] { { { { { 1234 } } } } }));\n" +
+ " }\n" +
+ "}\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@Documented\n" +
+ "@interface TakeType {\n" +
+ " Class value() default int[].class;\n" +
+ "}\n"
+ },
+ "1234");
+ }
+
+ public void testAnnotatedExtendedDimensions() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public class X {\n" +
+ " @NonNull String @Nullable [] f @NonNull [] = null;\n" +
+ " static @NonNull String @Nullable [] foo(@NonNull String @Nullable [] p @NonNull []) @NonNull [] {\n" +
+ " p = null;\n" +
+ " @NonNull String @Nullable [] l @NonNull [] = null;\n" +
+ " return p;\n" +
+ " }\n" +
+ "}\n",
+
+ "NonNull.java",
+ "import java.lang.annotation.*;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface NonNull {}\n",
+
+ "Nullable.java",
+ "import java.lang.annotation.*;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@interface Nullable {}\n",
+ },
+ "");
+ String expectedOutput =
+ " // Field descriptor #6 [[Ljava/lang/String;\n" +
+ " java.lang.String[][] f;\n" +
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #8 @NonNull(\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY, ARRAY]\n" +
+ " )\n" +
+ " #9 @Nullable(\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY]\n" +
+ " )\n" +
+ " #8 @NonNull(\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n" +
+ " \n" +
+ " // Method descriptor #11 ()V\n" +
+ " // Stack: 2, Locals: 1\n" +
+ " public X();\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 invokespecial java.lang.Object() [13]\n" +
+ " 4 aload_0 [this]\n" +
+ " 5 aconst_null\n" +
+ " 6 putfield X.f : java.lang.String[][] [15]\n" +
+ " 9 return\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 1]\n" +
+ " [pc: 4, line: 2]\n" +
+ " [pc: 9, line: 1]\n" +
+ " Local variable table:\n" +
+ " [pc: 0, pc: 10] local: this index: 0 type: X\n" +
+ " \n" +
+ " // Method descriptor #22 ([[Ljava/lang/String;)[[Ljava/lang/String;\n" +
+ " // Stack: 1, Locals: 2\n" +
+ " static java.lang.String[][] foo(java.lang.String[][] p);\n" +
+ " 0 aconst_null\n" +
+ " 1 astore_0 [p]\n" +
+ " 2 aconst_null\n" +
+ " 3 astore_1 [l]\n" +
+ " 4 aload_0 [p]\n" +
+ " 5 areturn\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 4]\n" +
+ " [pc: 2, line: 5]\n" +
+ " [pc: 4, line: 6]\n" +
+ " Local variable table:\n" +
+ " [pc: 0, pc: 6] local: p index: 0 type: java.lang.String[][]\n" +
+ " [pc: 4, pc: 6] local: l index: 1 type: java.lang.String[][]\n" +
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #8 @NonNull(\n" +
+ " target type = 0x40 LOCAL_VARIABLE\n" +
+ " local variable entries:\n" +
+ " [pc: 4, pc: 6] index: 1\n" +
+ " location = [ARRAY, ARRAY]\n" +
+ " )\n" +
+ " #9 @Nullable(\n" +
+ " target type = 0x40 LOCAL_VARIABLE\n" +
+ " local variable entries:\n" +
+ " [pc: 4, pc: 6] index: 1\n" +
+ " location = [ARRAY]\n" +
+ " )\n" +
+ " #8 @NonNull(\n" +
+ " target type = 0x40 LOCAL_VARIABLE\n" +
+ " local variable entries:\n" +
+ " [pc: 4, pc: 6] index: 1\n" +
+ " )\n" +
+ " RuntimeVisibleTypeAnnotations: \n" +
+ " #8 @NonNull(\n" +
+ " target type = 0x16 METHOD_FORMAL_PARAMETER\n" +
+ " method parameter index = 0\n" +
+ " location = [ARRAY, ARRAY]\n" +
+ " )\n" +
+ " #9 @Nullable(\n" +
+ " target type = 0x16 METHOD_FORMAL_PARAMETER\n" +
+ " method parameter index = 0\n" +
+ " location = [ARRAY]\n" +
+ " )\n" +
+ " #8 @NonNull(\n" +
+ " target type = 0x16 METHOD_FORMAL_PARAMETER\n" +
+ " method parameter index = 0\n" +
+ " )\n" +
+ " #8 @NonNull(\n" +
+ " target type = 0x14 METHOD_RETURN\n" +
+ " location = [ARRAY, ARRAY]\n" +
+ " )\n" +
+ " #9 @Nullable(\n" +
+ " target type = 0x14 METHOD_RETURN\n" +
+ " location = [ARRAY]\n" +
+ " )\n" +
+ " #8 @NonNull(\n" +
+ " target type = 0x14 METHOD_RETURN\n" +
+ " )\n" +
+ "}";
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=418347, [1.8][compiler] Type annotations dropped during code generation.
+ public void testPQTRArray() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "Outer.java",
+ "public class Outer<K> {\n" +
+ " class Inner<P> {\n" +
+ " }\n" +
+ " public @T(1) Outer<@T(2) String>.@T(3) Inner<@T(4) Integer> @T(5) [] omi @T(6) [];\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ " int value();\n" +
+ "}\n",
+ },
+ "");
+ String expectedOutput =
+ " public Outer$Inner[][] omi;\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 1 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY, ARRAY]\n" +
+ " )\n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 3 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY, ARRAY, INNER_TYPE]\n" +
+ " )\n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 5 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY]\n" +
+ " )\n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 6 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 2 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY, ARRAY, TYPE_ARGUMENT(0)]\n" +
+ " )\n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 4 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY, ARRAY, INNER_TYPE, TYPE_ARGUMENT(0)]\n" +
+ " )\n" +
+ " \n";
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator + "Outer.class", "Outer", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=418347, [1.8][compiler] Type annotations dropped during code generation.
+ public void testPQTRArray2() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "Outer.java",
+ "public class Outer<K1, K2> {\n" +
+ " class Inner<P1, P2> {\n" +
+ " }\n" +
+ " public @T(1) Outer<@T(2) String, @T(3) Inner>.@T(4) Inner<@T(5) Integer, @T(6) Outer.@T(7) Inner> @T(7) [] omi @T(8) [];\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ " int value();\n" +
+ "}\n",
+ },
+ "");
+ String expectedOutput =
+ " // Field descriptor #6 [[LOuter$Inner;\n" +
+ " // Signature: [[LOuter<Ljava/lang/String;LOuter$Inner;>.Inner<Ljava/lang/Integer;LOuter$Inner;>;\n" +
+ " public Outer$Inner[][] omi;\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 1 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY, ARRAY]\n" +
+ " )\n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 4 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY, ARRAY, INNER_TYPE]\n" +
+ " )\n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 7 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY]\n" +
+ " )\n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 8 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " )\n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 2 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY, ARRAY, TYPE_ARGUMENT(0)]\n" +
+ " )\n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 3 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY, ARRAY, TYPE_ARGUMENT(1), INNER_TYPE]\n" +
+ " )\n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 5 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY, ARRAY, INNER_TYPE, TYPE_ARGUMENT(0)]\n" +
+ " )\n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 6 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY, ARRAY, INNER_TYPE, TYPE_ARGUMENT(1)]\n" +
+ " )\n" +
+ " #10 @T(\n" +
+ " #11 value=(int) 7 (constant type)\n" +
+ " target type = 0x13 FIELD\n" +
+ " location = [ARRAY, ARRAY, INNER_TYPE, TYPE_ARGUMENT(1), INNER_TYPE]\n" +
+ " )\n" +
+ " \n";
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator + "Outer.class", "Outer", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=418347, [1.8][compiler] Type annotations dropped during code generation.
+ public void testConstructorResult() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ "}\n" +
+ "public class X {\n" +
+ " @T X() {}\n" +
+ " class Y {\n" +
+ " @T Y () {\n" +
+ " }\n" +
+ " }\n" +
+ "}\n",
+ },
+ "");
+ String expectedOutput =
+ " // Method descriptor #6 ()V\n" +
+ " // Stack: 1, Locals: 1\n" +
+ " X();\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 invokespecial java.lang.Object() [8]\n" +
+ " 4 return\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 7]\n" +
+ " Local variable table:\n" +
+ " [pc: 0, pc: 5] local: this index: 0 type: X\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #15 @T(\n" +
+ " target type = 0x14 METHOD_RETURN\n" +
+ " )\n" +
+ "\n";
+ String expectedOutForY =
+ " // Method descriptor #8 (LX;)V\n" +
+ " // Stack: 2, Locals: 2\n" +
+ " X$Y(X arg0);\n" +
+ " 0 aload_0 [this]\n" +
+ " 1 aload_1 [arg0]\n" +
+ " 2 putfield X$Y.this$0 : X [10]\n" +
+ " 5 aload_0 [this]\n" +
+ " 6 invokespecial java.lang.Object() [12]\n" +
+ " 9 return\n" +
+ " Line numbers:\n" +
+ " [pc: 0, line: 9]\n" +
+ " [pc: 9, line: 10]\n" +
+ " Local variable table:\n" +
+ " [pc: 0, pc: 10] local: this index: 0 type: X.Y\n" +
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #20 @T(\n" +
+ " target type = 0x14 METHOD_RETURN\n" +
+ " )\n" +
+ "\n";
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X$Y.class", "Y", expectedOutForY, ClassFileBytesDisassembler.SYSTEM);
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=418347, [1.8][compiler] Type annotations dropped during code generation.
+ public void test418347() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.*;\n" +
+ "import static java.lang.annotation.ElementType.*;\n" +
+ "@Target({TYPE_USE}) @interface P { }\n" +
+ "@Target({TYPE_USE}) @interface O { }\n" +
+ "@Target({TYPE_USE}) @interface I { }\n" +
+ "public abstract class X<T> {\n" +
+ " class Y<Q> {\n" +
+ " }\n" +
+ " void foo(@P Y<P> p) {}\n" +
+ "}\n",
+ },
+ "");
+ String expectedOutput =
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #24 @P(\n" +
+ " target type = 0x16 METHOD_FORMAL_PARAMETER\n" +
+ " method parameter index = 0\n" +
+ " location = [INNER_TYPE]\n" +
+ " )\n" +
+ "\n";
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=418347, [1.8][compiler] Type annotations dropped during code generation.
+ public void test418347a() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "import java.lang.annotation.*;\n" +
+ "import static java.lang.annotation.ElementType.*;\n" +
+ "@Target({TYPE_USE}) @interface P { }\n" +
+ "@Target({TYPE_USE}) @interface O { }\n" +
+ "@Target({TYPE_USE}) @interface I { }\n" +
+ "public abstract class X {\n" +
+ " class Y {\n" +
+ " class Z {}\n" +
+ " }\n" +
+ " void foo(@P X.@O Y.@I Z[] p) {}\n" +
+ "}\n",
+ },
+ "");
+ String expectedOutput =
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #19 @P(\n" +
+ " target type = 0x16 METHOD_FORMAL_PARAMETER\n" +
+ " method parameter index = 0\n" +
+ " location = [ARRAY]\n" +
+ " )\n" +
+ " #20 @O(\n" +
+ " target type = 0x16 METHOD_FORMAL_PARAMETER\n" +
+ " method parameter index = 0\n" +
+ " location = [ARRAY, INNER_TYPE]\n" +
+ " )\n" +
+ " #21 @I(\n" +
+ " target type = 0x16 METHOD_FORMAL_PARAMETER\n" +
+ " method parameter index = 0\n" +
+ " location = [ARRAY, INNER_TYPE, INNER_TYPE]\n" +
+ " )\n" +
+ "\n";
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=418347, [1.8][compiler] Type annotations dropped during code generation.
+ public void test418347b() throws Exception {
+ this.runConformTest(
+ new String[] {
+ "X.java",
+ "public abstract class X {\n" +
+ " java.util.List [][] l = new java.util.ArrayList @pkg.NonNull [0] @pkg.NonNull[]; \n" +
+ "}\n",
+ "pkg/NonNull.java",
+ "package pkg;\n" +
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "public @interface NonNull {\n" +
+ "}\n"
+ },
+ "");
+ String expectedOutput =
+ " RuntimeInvisibleTypeAnnotations: \n" +
+ " #21 @pkg.NonNull(\n" +
+ " target type = 0x44 NEW\n" +
+ " offset = 6\n" +
+ " )\n" +
+ " #21 @pkg.NonNull(\n" +
+ " target type = 0x44 NEW\n" +
+ " offset = 6\n" +
+ " location = [ARRAY]\n" +
+ " )\n" +
+ "}";
+ checkDisassembledClassFile(OUTPUT_DIR + File.separator + "X.class", "X", expectedOutput, ClassFileBytesDisassembler.SYSTEM);
+ }
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava8Tests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava8Tests.java
index 4a2cb719c..4aaaa42ee 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava8Tests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/RunAllJava8Tests.java
@@ -31,6 +31,7 @@ import org.eclipse.jdt.core.tests.dom.ASTConverterBugsTestJLS8;
import org.eclipse.jdt.core.tests.dom.ASTConverterTestAST8_2;
import org.eclipse.jdt.core.tests.dom.ConverterTestSetup;
import org.eclipse.jdt.core.tests.dom.TypeAnnotationsConverterTest;
+import org.eclipse.jdt.core.tests.dom.TypeBindingTests308;
import org.eclipse.jdt.core.tests.formatter.FormatterJSR308Tests;
import org.eclipse.jdt.core.tests.formatter.FormatterJSR335Tests;
import org.eclipse.jdt.core.tests.model.JavaSearchBugs8Tests;
@@ -60,6 +61,7 @@ public class RunAllJava8Tests extends TestCase {
ASTConverter15JLS8Test.class,
ASTConverter18Test.class,
ASTRewritingTest.class,
+ TypeBindingTests308.class,
};
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS4Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS4Test.java
index f0161190b..dbc6d3e3a 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS4Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS4Test.java
@@ -1,10 +1,14 @@
/*******************************************************************************
- * Copyright (c) 2011, 2012 IBM Corporation and others.
+ * Copyright (c) 2011, 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
* Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
@@ -64,6 +68,13 @@ public class ASTConverter15JLS4Test extends ConverterTestSetup {
}
}
+ /**
+ * @deprecated
+ */
+ private Type componentType(ArrayType array) {
+ return array.getComponentType();
+ }
+
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=234609 BindingKey#toSignature() fails with key from createWilcardTypeBindingKey(..)
public void test234609() throws JavaModelException {
@@ -1704,7 +1715,7 @@ public class ASTConverter15JLS4Test extends ConverterTestSetup {
checkSourceRange(type, "String[]", source);
assertTrue("not an array type", type.isArrayType());
ArrayType arrayType = (ArrayType) type;
- checkSourceRange(arrayType.getComponentType(), "String", source);
+ checkSourceRange(componentType(arrayType), "String", source);
assertEquals("Wrong extra dimensions", 1, singleVariableDeclaration.getExtraDimensions());
}
@@ -1732,7 +1743,7 @@ public class ASTConverter15JLS4Test extends ConverterTestSetup {
checkSourceRange(type, "String[]", source);
assertTrue("not an array type", type.isArrayType());
ArrayType arrayType = (ArrayType) type;
- checkSourceRange(arrayType.getComponentType(), "String", source);
+ checkSourceRange(componentType(arrayType), "String", source);
assertEquals("Wrong extra dimensions", 0, singleVariableDeclaration.getExtraDimensions());
}
/**
@@ -2423,11 +2434,11 @@ public class ASTConverter15JLS4Test extends ConverterTestSetup {
checkSourceRange(type, "Map<String, Double>[][]", source);
assertEquals("wrong type", ASTNode.ARRAY_TYPE, type.getNodeType());
ArrayType arrayType = (ArrayType) type;
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
checkSourceRange(type, "Map<String, Double>[]", source);
assertEquals("wrong type", ASTNode.ARRAY_TYPE, type.getNodeType());
arrayType = (ArrayType) type;
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
checkSourceRange(type, "Map<String, Double>", source);
}
@@ -2450,11 +2461,11 @@ public class ASTConverter15JLS4Test extends ConverterTestSetup {
checkSourceRange(type, "java.util.Map<String, Double>[][]", source);
assertEquals("wrong type", ASTNode.ARRAY_TYPE, type.getNodeType());
ArrayType arrayType = (ArrayType) type;
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
checkSourceRange(type, "java.util.Map<String, Double>[]", source);
assertEquals("wrong type", ASTNode.ARRAY_TYPE, type.getNodeType());
arrayType = (ArrayType) type;
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
checkSourceRange(type, "java.util.Map<String, Double>", source);
}
@@ -4114,7 +4125,7 @@ public class ASTConverter15JLS4Test extends ConverterTestSetup {
assertEquals("wrong dimensions", 1, typeBinding.getDimensions());
ArrayType arrayType = (ArrayType) type;
assertEquals("Wrong dimension", 1, arrayType.getDimensions());
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
assertTrue("Not a simple type", type.isSimpleType());
checkSourceRange(type, "String", contents);
assertEquals("Wrong extra dimension", 1, singleVariableDeclaration.getExtraDimensions());
@@ -4498,7 +4509,7 @@ public class ASTConverter15JLS4Test extends ConverterTestSetup {
assertEquals("wrong dimensions", 1, typeBinding.getDimensions());
ArrayType arrayType = (ArrayType) type;
assertEquals("Wrong dimension", 1, arrayType.getDimensions());
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
assertTrue("Not a simple type", type.isSimpleType());
checkSourceRange(type, "String", contents);
assertEquals("Wrong extra dimension", 0, singleVariableDeclaration.getExtraDimensions());
@@ -11182,7 +11193,7 @@ public class ASTConverter15JLS4Test extends ConverterTestSetup {
ITypeBinding binding = type.resolveBinding();
assertNotNull("No binding", binding);
assertEquals("Wrong qualified name", "test0347.Outer<java.lang.Integer>.Inner<java.lang.Double>[]", binding.getQualifiedName());
- Type componentType = type.getComponentType();
+ Type componentType = componentType(type);
binding = componentType.resolveBinding();
assertNotNull("No binding", binding);
assertEquals("Wrong qualified name", "test0347.Outer<java.lang.Integer>.Inner<java.lang.Double>", binding.getQualifiedName());
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS8Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS8Test.java
index f4b1528d5..e2c440487 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS8Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter15JLS8Test.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2012 IBM Corporation and others.
+ * Copyright (c) 2011, 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
@@ -1708,7 +1708,7 @@ public class ASTConverter15JLS8Test extends ConverterTestSetup {
checkSourceRange(type, "String[]", source);
assertTrue("not an array type", type.isArrayType());
ArrayType arrayType = (ArrayType) type;
- checkSourceRange(arrayType.getComponentType(), "String", source);
+ checkSourceRange(arrayType.getElementType(), "String", source);
assertEquals("Wrong extra dimensions", 1, singleVariableDeclaration.getExtraDimensions());
}
@@ -1736,7 +1736,7 @@ public class ASTConverter15JLS8Test extends ConverterTestSetup {
checkSourceRange(type, "String[]", source);
assertTrue("not an array type", type.isArrayType());
ArrayType arrayType = (ArrayType) type;
- checkSourceRange(arrayType.getComponentType(), "String", source);
+ checkSourceRange(arrayType.getElementType(), "String", source);
assertEquals("Wrong extra dimensions", 0, singleVariableDeclaration.getExtraDimensions());
}
/**
@@ -2427,12 +2427,9 @@ public class ASTConverter15JLS8Test extends ConverterTestSetup {
checkSourceRange(type, "Map<String, Double>[][]", source);
assertEquals("wrong type", ASTNode.ARRAY_TYPE, type.getNodeType());
ArrayType arrayType = (ArrayType) type;
- type = arrayType.getComponentType();
- checkSourceRange(type, "Map<String, Double>[]", source);
- assertEquals("wrong type", ASTNode.ARRAY_TYPE, type.getNodeType());
- arrayType = (ArrayType) type;
- type = arrayType.getComponentType();
+ type = arrayType.getElementType();
checkSourceRange(type, "Map<String, Double>", source);
+ assertEquals("wrong type", ASTNode.PARAMETERIZED_TYPE, type.getNodeType());
}
/*
@@ -2454,12 +2451,9 @@ public class ASTConverter15JLS8Test extends ConverterTestSetup {
checkSourceRange(type, "java.util.Map<String, Double>[][]", source);
assertEquals("wrong type", ASTNode.ARRAY_TYPE, type.getNodeType());
ArrayType arrayType = (ArrayType) type;
- type = arrayType.getComponentType();
- checkSourceRange(type, "java.util.Map<String, Double>[]", source);
- assertEquals("wrong type", ASTNode.ARRAY_TYPE, type.getNodeType());
- arrayType = (ArrayType) type;
- type = arrayType.getComponentType();
+ type = arrayType.getElementType();
checkSourceRange(type, "java.util.Map<String, Double>", source);
+ assertEquals("wrong type", ASTNode.PARAMETERIZED_TYPE, type.getNodeType());
}
/*
@@ -4118,7 +4112,7 @@ public class ASTConverter15JLS8Test extends ConverterTestSetup {
assertEquals("wrong dimensions", 1, typeBinding.getDimensions());
ArrayType arrayType = (ArrayType) type;
assertEquals("Wrong dimension", 1, arrayType.getDimensions());
- type = arrayType.getComponentType();
+ type = arrayType.getElementType();
assertTrue("Not a simple type", type.isSimpleType());
checkSourceRange(type, "String", contents);
assertEquals("Wrong extra dimension", 1, singleVariableDeclaration.getExtraDimensions());
@@ -4502,7 +4496,7 @@ public class ASTConverter15JLS8Test extends ConverterTestSetup {
assertEquals("wrong dimensions", 1, typeBinding.getDimensions());
ArrayType arrayType = (ArrayType) type;
assertEquals("Wrong dimension", 1, arrayType.getDimensions());
- type = arrayType.getComponentType();
+ type = arrayType.getElementType();
assertTrue("Not a simple type", type.isSimpleType());
checkSourceRange(type, "String", contents);
assertEquals("Wrong extra dimension", 0, singleVariableDeclaration.getExtraDimensions());
@@ -11186,7 +11180,7 @@ public class ASTConverter15JLS8Test extends ConverterTestSetup {
ITypeBinding binding = type.resolveBinding();
assertNotNull("No binding", binding);
assertEquals("Wrong qualified name", "test0347.Outer<java.lang.Integer>.Inner<java.lang.Double>[]", binding.getQualifiedName());
- Type componentType = type.getComponentType();
+ Type componentType = type.getElementType();
binding = componentType.resolveBinding();
assertNotNull("No binding", binding);
assertEquals("Wrong qualified name", "test0347.Outer<java.lang.Integer>.Inner<java.lang.Double>", binding.getQualifiedName());
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 aec1a3c98..094d81358 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
@@ -78,6 +78,13 @@ public class ASTConverter15Test extends ConverterTestSetup {
}
}
+ /**
+ * @deprecated
+ */
+ private Type componentType(ArrayType array) {
+ return array.getComponentType();
+ }
+
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=234609 BindingKey#toSignature() fails with key from createWilcardTypeBindingKey(..)
public void test234609() throws JavaModelException {
@@ -1718,7 +1725,7 @@ public class ASTConverter15Test extends ConverterTestSetup {
checkSourceRange(type, "String[]", source);
assertTrue("not an array type", type.isArrayType());
ArrayType arrayType = (ArrayType) type;
- checkSourceRange(arrayType.getComponentType(), "String", source);
+ checkSourceRange(componentType(arrayType), "String", source);
assertEquals("Wrong extra dimensions", 1, singleVariableDeclaration.getExtraDimensions());
}
@@ -1746,7 +1753,7 @@ public class ASTConverter15Test extends ConverterTestSetup {
checkSourceRange(type, "String[]", source);
assertTrue("not an array type", type.isArrayType());
ArrayType arrayType = (ArrayType) type;
- checkSourceRange(arrayType.getComponentType(), "String", source);
+ checkSourceRange(componentType(arrayType), "String", source);
assertEquals("Wrong extra dimensions", 0, singleVariableDeclaration.getExtraDimensions());
}
/**
@@ -2437,11 +2444,11 @@ public class ASTConverter15Test extends ConverterTestSetup {
checkSourceRange(type, "Map<String, Double>[][]", source);
assertEquals("wrong type", ASTNode.ARRAY_TYPE, type.getNodeType());
ArrayType arrayType = (ArrayType) type;
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
checkSourceRange(type, "Map<String, Double>[]", source);
assertEquals("wrong type", ASTNode.ARRAY_TYPE, type.getNodeType());
arrayType = (ArrayType) type;
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
checkSourceRange(type, "Map<String, Double>", source);
}
@@ -2464,11 +2471,11 @@ public class ASTConverter15Test extends ConverterTestSetup {
checkSourceRange(type, "java.util.Map<String, Double>[][]", source);
assertEquals("wrong type", ASTNode.ARRAY_TYPE, type.getNodeType());
ArrayType arrayType = (ArrayType) type;
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
checkSourceRange(type, "java.util.Map<String, Double>[]", source);
assertEquals("wrong type", ASTNode.ARRAY_TYPE, type.getNodeType());
arrayType = (ArrayType) type;
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
checkSourceRange(type, "java.util.Map<String, Double>", source);
}
@@ -4128,7 +4135,7 @@ public class ASTConverter15Test extends ConverterTestSetup {
assertEquals("wrong dimensions", 1, typeBinding.getDimensions());
ArrayType arrayType = (ArrayType) type;
assertEquals("Wrong dimension", 1, arrayType.getDimensions());
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
assertTrue("Not a simple type", type.isSimpleType());
checkSourceRange(type, "String", contents);
assertEquals("Wrong extra dimension", 1, singleVariableDeclaration.getExtraDimensions());
@@ -4512,7 +4519,7 @@ public class ASTConverter15Test extends ConverterTestSetup {
assertEquals("wrong dimensions", 1, typeBinding.getDimensions());
ArrayType arrayType = (ArrayType) type;
assertEquals("Wrong dimension", 1, arrayType.getDimensions());
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
assertTrue("Not a simple type", type.isSimpleType());
checkSourceRange(type, "String", contents);
assertEquals("Wrong extra dimension", 0, singleVariableDeclaration.getExtraDimensions());
@@ -11197,7 +11204,7 @@ public class ASTConverter15Test extends ConverterTestSetup {
ITypeBinding binding = type.resolveBinding();
assertNotNull("No binding", binding);
assertEquals("Wrong qualified name", "test0347.Outer<java.lang.Integer>.Inner<java.lang.Double>[]", binding.getQualifiedName());
- Type componentType = type.getComponentType();
+ Type componentType = componentType(type);
binding = componentType.resolveBinding();
assertNotNull("No binding", binding);
assertEquals("Wrong qualified name", "test0347.Outer<java.lang.Integer>.Inner<java.lang.Double>", binding.getQualifiedName());
@@ -11323,7 +11330,7 @@ public class ASTConverter15Test extends ConverterTestSetup {
assertTrue("Not a compilation unit", result.getNodeType() == ASTNode.COMPILATION_UNIT);
CompilationUnit unit = (CompilationUnit) result;
MethodDeclaration methodDeclaration = (MethodDeclaration) getASTNode(unit, 0, 0);
- Type componentType = ((ArrayType)methodDeclaration.getReturnType2()).getComponentType();
+ Type componentType = componentType(((ArrayType)methodDeclaration.getReturnType2()));
ITypeBinding typeBinding = componentType.resolveBinding();
assertEquals("Wrong fully qualified name", "test0351.I1", typeBinding.getQualifiedName());
}
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 de2836062..73afc7cec 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
@@ -273,13 +273,13 @@ public class ASTConverter18Test extends ConverterTestSetup {
ITypeBinding binding = type.resolveBinding();
assertNotNull("No binding", binding);
assertEquals("Wrong qualified name", "test0004.Outer<java.lang.Integer>.Inner<java.lang.Double>[]", binding.getQualifiedName());
- Type componentType = type.getComponentType();
- binding = componentType.resolveBinding();
+ Type elementType = type.getElementType();
+ binding = elementType.resolveBinding();
assertNotNull("No binding", binding);
assertEquals("Wrong qualified name",
"test0004.Outer<java.lang.Integer>.Inner<java.lang.Double>", binding.getQualifiedName());
- assertTrue("Not parameterized", componentType.isParameterizedType());
- ParameterizedType parameterizedType = (ParameterizedType) componentType;
+ assertTrue("Not parameterized", elementType.isParameterizedType());
+ ParameterizedType parameterizedType = (ParameterizedType) elementType;
Type type2 = parameterizedType.getType();
assertTrue("Not qualified", type2.isQualifiedType());
QualifiedType qualifiedType = (QualifiedType) type2;
@@ -1139,13 +1139,12 @@ public class ASTConverter18Test extends ConverterTestSetup {
Type type = creation.getType();
assertEquals("Incorrect type", true, type.isArrayType());
checkSourceRange(type, "@Marker2 int @Marker @Marker2 [2] @Marker2 @Marker3 [bar()] @Marker3 @Marker []", contents.toCharArray());
- assertEquals("Incorrect annotations", "@Marker3 @Marker ", convertAnnotationsList(((ArrayType) type).annotations()));
- type = ((ArrayType) type).getComponentType();
- assertEquals("Incorrect type", true, type.isArrayType());
- assertEquals("Incorrect annotations", "@Marker2 @Marker3 ", convertAnnotationsList(((ArrayType) type).annotations()));
- type = ((ArrayType) type).getComponentType();
- assertEquals("Incorrect type", true, type.isArrayType());
- assertEquals("Incorrect annotations", "@Marker @Marker2 ", convertAnnotationsList(((ArrayType) type).annotations()));
+ ExtraDimension extraDimension = ((ArrayType) type).getDimensionAt(0);
+ assertEquals("Incorrect annotations", "@Marker3 @Marker ", convertAnnotationsList(extraDimension.annotations()));
+ extraDimension = ((ArrayType) type).getDimensionAt(1);
+ assertEquals("Incorrect annotations", "@Marker2 @Marker3 ", convertAnnotationsList(extraDimension.annotations()));
+ extraDimension = ((ArrayType) type).getDimensionAt(2);
+ assertEquals("Incorrect annotations", "@Marker @Marker2 ", convertAnnotationsList(extraDimension.annotations()));
List dimensions = creation.dimensions();
assertEquals("Incorrect expressions", 2, dimensions.size());
assertEquals("Incorrect expressions", "2", dimensions.get(0).toString());
@@ -1159,13 +1158,12 @@ public class ASTConverter18Test extends ConverterTestSetup {
type = creation.getType();
assertEquals("Incorrect type", true, type.isArrayType());
- assertEquals("Incorrect annotations", "@Marker2 @Marker3 ", convertAnnotationsList(((ArrayType) type).annotations()));
- type = ((ArrayType) type).getComponentType();
- assertEquals("Incorrect type", true, type.isArrayType());
- assertEquals("Incorrect annotations", "@Marker @Marker2 ", convertAnnotationsList(((ArrayType) type).annotations()));
- type = ((ArrayType) type).getComponentType();
- assertEquals("Incorrect type", true, type.isArrayType());
- assertEquals("Incorrect annotations", "@Marker3 @Marker ", convertAnnotationsList(((ArrayType) type).annotations()));
+ extraDimension = ((ArrayType) type).getDimensionAt(0);
+ assertEquals("Incorrect annotations", "@Marker2 @Marker3 ", convertAnnotationsList(extraDimension.annotations()));
+ extraDimension = ((ArrayType) type).getDimensionAt(1);
+ assertEquals("Incorrect annotations", "@Marker @Marker2 ", convertAnnotationsList(extraDimension.annotations()));
+ extraDimension = ((ArrayType) type).getDimensionAt(2);
+ assertEquals("Incorrect annotations", "@Marker3 @Marker ", convertAnnotationsList(extraDimension.annotations()));
dimensions = creation.dimensions();
assertEquals("Incorrect expressions", 2, dimensions.size());
assertEquals("Incorrect expressions", "2", dimensions.get(0).toString());
@@ -1238,12 +1236,6 @@ public class ASTConverter18Test extends ConverterTestSetup {
Type type = creation.getType();
assertEquals("Incorrect type", true, type.isArrayType());
assertEquals("Type should be malformed", ASTNode.MALFORMED, (type.getFlags() & ASTNode.MALFORMED));
- type = ((ArrayType) type).getComponentType();
- assertEquals("Incorrect type", true, type.isArrayType());
- assertEquals("Type should be malformed", ASTNode.MALFORMED, (type.getFlags() & ASTNode.MALFORMED));
- type = ((ArrayType) type).getComponentType();
- assertEquals("Incorrect type", true, type.isArrayType());
- assertEquals("Type should be malformed", ASTNode.MALFORMED, (type.getFlags() & ASTNode.MALFORMED));
}
/**
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=399768
@@ -1614,14 +1606,14 @@ public class ASTConverter18Test extends ConverterTestSetup {
Expression expression = fragment.getInitializer();
assertTrue(expression instanceof LambdaExpression);
LambdaExpression lambdaExpression = (LambdaExpression)expression;
- assertEquals("(int[] ia) -> {\n return ia.clone();\n}\n", lambdaExpression.toString());
+ assertEquals("(int [] ia) -> {\n return ia.clone();\n}\n", lambdaExpression.toString());
IMethodBinding binding = lambdaExpression.resolveMethodBinding();
assertEquals("private static java.lang.Object lambda$0(int[]) ", binding.toString());
assertTrue(lambdaExpression.parameters().size() == 1);
VariableDeclaration variableDeclaration = (VariableDeclaration) lambdaExpression.parameters().get(0);
assertTrue(variableDeclaration instanceof SingleVariableDeclaration);
SingleVariableDeclaration singleVariableDeclaration = (SingleVariableDeclaration)variableDeclaration;
- assertEquals("int[] ia", singleVariableDeclaration.toString());
+ assertEquals("int [] ia", singleVariableDeclaration.toString());
}
/**
@@ -2193,6 +2185,11 @@ public class ASTConverter18Test extends ConverterTestSetup {
ITypeBinding binding = qualifiedType.resolveBinding();
assertNotNull("No binding", binding);
assertEquals("Wrong qualified name", "test404489.bug.X.Y", binding.getQualifiedName());
+ 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", binding.getQualifiedName());
List annotations = qualifiedType.annotations();
assertTrue(annotations.size() == 1);
MarkerAnnotation marker = (MarkerAnnotation) annotations.get(0);
@@ -2212,11 +2209,11 @@ public class ASTConverter18Test extends ConverterTestSetup {
assertNotNull("No binding", binding);
assertEquals("Wrong qualified name", "test404489.bug.B", binding.getQualifiedName());
assertTrue(qualifiedType.getQualifier().isSimpleType());
- SimpleType simpleType = (SimpleType) qualifiedType.getQualifier();
+ 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());
+ assertEquals("Wrong qualified name", "test404489.bug.X", binding.getQualifiedName());
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=404489
@@ -2648,5 +2645,631 @@ public class ASTConverter18Test extends ConverterTestSetup {
typeBinding = type.resolveBinding();
assertFalse("A Functional interface", typeBinding.isFunctionalInterface());
}
+ /**
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=417017
+ *
+ * @throws JavaModelException
+ */
+ public void test417017a() throws JavaModelException {
+ this.workingCopy = getWorkingCopy("/Converter18/src/test417017/X.java",
+ true/* resolve */);
+ String contents = "package test417017;"
+ + "interface I {\n"
+ + " int foo(int x);\n"
+ + "}\n"
+ + "public class X {\n"
+ + " void fun(int a) {\n"
+ +" I i1 = x1-> x1;\n"
+ +" I i2 = xxx-> {\n"
+ +" i1.foo(a);\n"
+ +" return xxx;\n"
+ +" };\n"
+ +" }\n"
+ +"}\n";
+ CompilationUnit cu = (CompilationUnit) buildAST(contents, this.workingCopy);
+ TypeDeclaration typedeclaration = (TypeDeclaration) getASTNode(cu, 1);
+ MethodDeclaration methodDeclaration = typedeclaration.getMethods()[0];
+ VariableDeclarationFragment vdf= (VariableDeclarationFragment) ((VariableDeclarationStatement) methodDeclaration.getBody().statements().get(1)).fragments().get(0);
+ LambdaExpression lambda= (LambdaExpression) vdf.getInitializer();
+ List parameters = lambda.parameters();
+ assertTrue("Incorrect Number of parameters", parameters.size() == 1);
+ ITypeBinding[] parameterTypes= lambda.resolveMethodBinding().getParameterTypes();
+ assertTrue("Incorrect Number of parameter type", parameterTypes.length == 1);
+ assertEquals("Incorrect parameter type", "int", parameterTypes[0].toString());
+ }
+ /**
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=417017
+ *
+ * @throws JavaModelException
+ */
+ public void test417017b() throws JavaModelException {
+ this.workingCopy = getWorkingCopy("/Converter18/src/test417017/X.java",
+ true/* resolve */);
+ String contents = "package test417017;" +
+ "interface I1 {\n" +
+ " int foo(int a);\n" +
+ "}\n" +
+ "\n" +
+ "interface I2 {\n" +
+ " public default int foo() {\n" +
+ " I1 i1 = (a) -> {\n" +
+ " return a;\n" +
+ " };\n" +
+ " //return 0;\n" + // Error on purpose
+ " }\n" +
+ "}\n" ;
+ CompilationUnit cu = (CompilationUnit) buildAST(contents, this.workingCopy, false);
+ TypeDeclaration typedeclaration = (TypeDeclaration) getASTNode(cu, 1);
+ MethodDeclaration methodDeclaration = typedeclaration.getMethods()[0];
+ VariableDeclarationFragment vdf= (VariableDeclarationFragment) ((VariableDeclarationStatement) methodDeclaration.getBody().statements().get(0)).fragments().get(0);
+ LambdaExpression lambda= (LambdaExpression) vdf.getInitializer();
+ List parameters = lambda.parameters();
+ assertTrue("Incorrect Number of parameters", parameters.size() == 1);
+ ITypeBinding[] parameterTypes= lambda.resolveMethodBinding().getParameterTypes();
+ assertTrue("Incorrect Number of parameter type", parameterTypes.length == 1);
+ assertEquals("Incorrect parameter type", "int", parameterTypes[0].toString());
+ }
+ /**
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=417017
+ *
+ * @throws JavaModelException
+ */
+ public void test417017c() throws JavaModelException {
+ this.workingCopy = getWorkingCopy("/Converter18/src/test417017/X.java",
+ true/* resolve */);
+ String contents = "package test417017;" +
+ "interface I1 {\n" +
+ " int foo(int a);\n" +
+ "}\n" +
+ "\n" +
+ "interface I2 {\n" +
+ " public default int foo() {\n" +
+ " I1 i1 = (float a) -> {\n" +
+ " return a;\n" +
+ " };\n" +
+ " //return 0;\n" + // Error on purpose
+ " }\n" +
+ "}\n" ;
+ CompilationUnit cu = (CompilationUnit) buildAST(contents, this.workingCopy, false);
+ TypeDeclaration typedeclaration = (TypeDeclaration) getASTNode(cu, 1);
+ MethodDeclaration methodDeclaration = typedeclaration.getMethods()[0];
+ VariableDeclarationFragment vdf= (VariableDeclarationFragment) ((VariableDeclarationStatement) methodDeclaration.getBody().statements().get(0)).fragments().get(0);
+ LambdaExpression lambda= (LambdaExpression) vdf.getInitializer();
+ List parameters = lambda.parameters();
+ assertTrue("Incorrect Number of parameters", parameters.size() == 1);
+ ITypeBinding[] parameterTypes= lambda.resolveMethodBinding().getParameterTypes();
+ assertTrue("Incorrect Number of parameter type", parameterTypes.length == 1);
+ assertEquals("Incorrect parameter type", "float", parameterTypes[0].toString());
+ }
+ /**
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=417017
+ *
+ * @throws JavaModelException
+ */
+ public void test417017d() throws JavaModelException {
+ this.workingCopy = getWorkingCopy("/Converter18/src/test399794/X.java",
+ true/* resolve */);
+ String contents = "package test399794;" +
+ "interface I {\n" +
+ " void foo(X x);\n" +
+ "}\n" +
+ "public class X {\n" +
+ " void foo(X x) {\n" +
+ " }\n" +
+ " I i = this::foo;\n" +
+ "}\n";
+
+ CompilationUnit cu = (CompilationUnit) buildAST(contents, this.workingCopy);
+ TypeDeclaration typeDeclaration = (TypeDeclaration) getASTNode(cu, 1);
+ FieldDeclaration field = typeDeclaration.getFields()[0];
+
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ Expression expression = fragment.getInitializer();
+ ExpressionMethodReference methodReference = (ExpressionMethodReference) expression;
+ IMethodBinding methodBinding = methodReference.resolveMethodBinding();
+ assertNotNull(methodBinding);
+ ITypeBinding [] parameterTypes = methodBinding.getParameterTypes();
+ assertTrue("Incorrect Number of parameter type", parameterTypes.length == 1);
+ assertEquals("Incorrect parameter type", "X", parameterTypes[0].getName());
+ }
+ /**
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=417017
+ *
+ * @throws JavaModelException
+ */
+ public void test417017e() throws JavaModelException {
+ this.workingCopy = getWorkingCopy("/Converter18/src/test399794/X.java",
+ true/* resolve */);
+ String contents = "package test399794;" +
+ "interface I {\n" +
+ " int [] foo(int x);\n" +
+ "}\n" +
+ "public class X {\n" +
+ " I i = int []::new;\n" +
+ "}\n";
+
+ CompilationUnit cu = (CompilationUnit) buildAST(contents, this.workingCopy);
+ TypeDeclaration typeDeclaration = (TypeDeclaration) getASTNode(cu, 1);
+ FieldDeclaration field = typeDeclaration.getFields()[0];
+
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ Expression expression = fragment.getInitializer();
+ CreationReference creationReference = (CreationReference) expression;
+ IMethodBinding methodBinding = creationReference.resolveMethodBinding();
+ assertNotNull(methodBinding);
+ assertEquals("Wrong name", "lambda$0", methodBinding.getName());
+ ITypeBinding [] parameterTypes = methodBinding.getParameterTypes();
+ assertTrue("Incorrect Number of parameter type", parameterTypes.length == 1);
+ assertEquals("Incorrect parameter type", "int", parameterTypes[0].getName());
+ }
+
+ /**
+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=417017
+ *
+ * @throws JavaModelException
+ */
+ public void test417017f() throws JavaModelException {
+ this.workingCopy = getWorkingCopy("/Converter18/src/test399794/X.java",
+ true/* resolve */);
+ String contents = "package test399794;" +
+ "interface I {\n" +
+ " void foo(X x);\n" +
+ "}\n" +
+ "public class X {\n" +
+ " private void foo(X x) {\n" +
+ " }\n" +
+ " class Y {\n" +
+ " I i = X.this::foo;\n" +
+ " }\n" +
+ "}\n";
+
+ CompilationUnit cu = (CompilationUnit) buildAST(contents, this.workingCopy);
+ TypeDeclaration typeDeclaration = (TypeDeclaration) getASTNode(cu, 1);
+ typeDeclaration = typeDeclaration.getTypes()[0];
+ FieldDeclaration field = typeDeclaration.getFields()[0];
+
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ Expression expression = fragment.getInitializer();
+ ExpressionMethodReference reference = (ExpressionMethodReference) expression;
+ IMethodBinding methodBinding = reference.resolveMethodBinding();
+ assertNotNull(methodBinding);
+ assertEquals("Wrong name", "foo", methodBinding.getName());
+ ITypeBinding [] parameterTypes = methodBinding.getParameterTypes();
+ assertTrue("Incorrect Number of parameter type", parameterTypes.length == 1);
+ assertEquals("Incorrect parameter type", "X", parameterTypes[0].getName());
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=413942
+ // also refer https://bugs.eclipse.org/bugs/show_bug.cgi?id=413569
+ public void testBug413942() throws JavaModelException {
+ String contents =
+ "public class X extends @NonNull(int[].class) Object {\n" +
+ " Object field = new ArrayList< @NonEmpty(0) int @NonNull(value1 = 1) [] @NonEmpty(1) [ ]>() ;\n" +
+ " @Annot int @Annot1 [] a1 @Annot2 @Annot3 @NonNull (value = int[].class, value1 = 0)[/* [] */ ] @Annot3 @Annot2 [] @Annot4 [];\n" +
+ " int[] xxx[];\n" +
+ " int [][] ii = new int[2][3];" +
+ " ArrayList<int[]> [][] yyy; // source ranges already broken in AST.JLS4\n" +
+ " ArrayList<int[][]> [][][][] zzz;\n" +
+ " ArrayList<Float> [][][] zzz2;\n" +
+ " Object a = new ArrayList< @TakeType(int[][].class) int @TakeType(float.class) [] @TakeType(double.class) []>() ;\n" +
+ " Object b = new @NonNull(value1 = Math.PI) ArrayList< >() ; \n" +
+ " Object c = new ArrayList<@NonNull(value1= Math.PI ) Object[]>() ;\n" +
+ "\n" +
+ " int foo(@TakeType(int[].class)int i ) @TakeType(int[].class) [] {\n" +
+ " int[] arr = new int[2];\n" +
+ " for (String tab @TakeType(int[].class) [] = null;; ++i) { break; }\n" +
+ " for (@Deprecated String tab@TakeType(int[].class) [][] = null;; ++i) {}\n" +
+ " }\n" +
+ " int bar(int [] /*@TakeType(int[].class)*/ [] a ) {\n" +
+ " return 0;\n" +
+ " }\n" +
+ "public int var1(int @TakeType(int[].class)... args) { return 0;}\n" +
+ "public int var2(int @Annot ... args) { return 0;}\n" +
+ "}\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@Documented\n" +
+ "@interface NonNull {\n" +
+ " Class value() default int.class;\n" +
+ " double value1() default 0;\n" +
+ "}\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@Documented\n" +
+ "@interface NonEmpty {\n" +
+ " int value() default 0;\n" +
+ "}\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@Documented\n" +
+ "@interface TakeType {\n" +
+ " Class value() default int[].class;\n" +
+ "}\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@Documented\n" +
+ "@interface Annot {}\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@Documented\n" +
+ "@interface Annot1 {}\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@Documented\n" +
+ "@interface Annot2 {}\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@Documented\n" +
+ "@interface Annot3 {}\n" +
+ "\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@Retention(RetentionPolicy.RUNTIME)\n" +
+ "@Documented\n" +
+ "@interface Annot4 {}\n" +
+ "\n";
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy, false);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit unit = (CompilationUnit) node;
+
+ TypeDeclaration type = (TypeDeclaration) unit.types().get(0);
+ SimpleType simpleType = (SimpleType) type.getSuperclassType();
+ checkSourceRange(simpleType, "@NonNull(int[].class) Object", contents);
+ SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) simpleType.annotations().get(0);
+ checkSourceRange(singleMemberAnnotation, "@NonNull(int[].class)", contents);
+ TypeLiteral typeLiteral = (TypeLiteral) singleMemberAnnotation.getValue();
+ checkSourceRange(typeLiteral, "int[].class", contents);
+ ArrayType arrayType = (ArrayType) typeLiteral.getType();
+ checkSourceRange(arrayType, "int[]", contents);
+
+ int count = 0;
+ FieldDeclaration field = (FieldDeclaration) type.bodyDeclarations().get(count++);
+ checkSourceRange(field, "Object field = new ArrayList< @NonEmpty(0) int @NonNull(value1 = 1) [] @NonEmpty(1) [ ]>() ;", contents);
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ ClassInstanceCreation instance = (ClassInstanceCreation) fragment.getInitializer();
+ ParameterizedType parameterizedType = (ParameterizedType) instance.getType();
+ arrayType = (ArrayType) parameterizedType.typeArguments().get(0);
+ checkSourceRange(arrayType, "@NonEmpty(0) int @NonNull(value1 = 1) [] @NonEmpty(1) [ ]", contents);
+ PrimitiveType primitiveType = (PrimitiveType) arrayType.getElementType();
+ checkSourceRange(primitiveType, "@NonEmpty(0) int", contents);
+ ExtraDimension extraDimension = arrayType.getDimensionAt(1);
+ checkSourceRange(extraDimension, "@NonNull(value1 = 1) []", contents);
+ extraDimension = arrayType.getDimensionAt(0);
+ checkSourceRange(extraDimension, "@NonEmpty(1) [ ]", contents);
+
+ field = (FieldDeclaration) type.bodyDeclarations().get(count++);
+ checkSourceRange(field, "@Annot int @Annot1 [] a1 @Annot2 @Annot3 @NonNull (value = int[].class, value1 = 0)[/* [] */ ] @Annot3 @Annot2 [] @Annot4 [];", contents);
+ arrayType = (ArrayType) field.getType();
+ checkSourceRange(arrayType, "int @Annot1 []", contents);
+ fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ extraDimension = (ExtraDimension) fragment.extraDimensions().get(0);
+ checkSourceRange(extraDimension, "@Annot2 @Annot3 @NonNull (value = int[].class, value1 = 0)[/* [] */ ]", contents);
+ extraDimension = (ExtraDimension) fragment.extraDimensions().get(1);
+ checkSourceRange(extraDimension, "@Annot3 @Annot2 []", contents);
+
+ field = (FieldDeclaration) type.bodyDeclarations().get(count++);
+ checkSourceRange(field, "int[] xxx[];", contents);
+ assertTrue(field.getType().isArrayType());
+ arrayType = (ArrayType) field.getType();
+ checkSourceRange(arrayType, "int[]", contents);
+
+ field = (FieldDeclaration) type.bodyDeclarations().get(count++);
+ checkSourceRange(field, "int [][] ii = new int[2][3];", contents);
+ arrayType = (ArrayType) field.getType();
+ checkSourceRange(arrayType, "int [][]", contents);
+ fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ ArrayCreation arrayCreation = (ArrayCreation) fragment.getInitializer();
+ arrayType = arrayCreation.getType();
+ assertTrue(arrayType.getElementType().isPrimitiveType());
+ assertTrue(arrayType.getDimensions() == 2);
+
+ field = (FieldDeclaration) type.bodyDeclarations().get(count++);
+ checkSourceRange(field, "ArrayList<int[]> [][] yyy;", contents);
+ arrayType = (ArrayType) field.getType();
+ checkSourceRange(arrayType, "ArrayList<int[]> [][]", contents);
+
+ field = (FieldDeclaration) type.bodyDeclarations().get(count++);
+ checkSourceRange(field, "ArrayList<int[][]> [][][][] zzz;", contents);
+ arrayType = (ArrayType) field.getType();
+ assertTrue(arrayType.getElementType().isParameterizedType());
+ assertTrue(arrayType.getDimensions() == 4);
+
+ field = (FieldDeclaration) type.bodyDeclarations().get(count++);
+ checkSourceRange(field, "ArrayList<Float> [][][] zzz2;", contents);
+ arrayType = (ArrayType) field.getType();
+ assertTrue(arrayType.getElementType().isParameterizedType());
+ assertTrue(arrayType.getDimensions() == 3);
+
+ field = (FieldDeclaration) type.bodyDeclarations().get(count++);
+ checkSourceRange(field, "Object a = new ArrayList< @TakeType(int[][].class) int @TakeType(float.class) [] @TakeType(double.class) []>() ;", contents);
+ fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ ClassInstanceCreation classInstanceCreation = (ClassInstanceCreation) fragment.getInitializer();
+ parameterizedType = (ParameterizedType) classInstanceCreation.getType();
+ arrayType = (ArrayType) parameterizedType.typeArguments().get(0);
+ checkSourceRange(arrayType, "@TakeType(int[][].class) int @TakeType(float.class) [] @TakeType(double.class) []", contents);
+ checkSourceRange(arrayType.getElementType(), "@TakeType(int[][].class) int", contents);
+ assertTrue(arrayType.getElementType().isPrimitiveType());
+ extraDimension = arrayType.getDimensionAt(1);
+ checkSourceRange(extraDimension, "@TakeType(float.class) []", contents);
+ extraDimension = arrayType.getDimensionAt(0);
+ Annotation annotation = (Annotation) extraDimension.annotations().get(0);
+ assertTrue(annotation.isSingleMemberAnnotation());
+ singleMemberAnnotation = (SingleMemberAnnotation) annotation;
+ typeLiteral = (TypeLiteral) singleMemberAnnotation.getValue();
+ checkSourceRange(typeLiteral, "double.class", contents);
+
+ field = (FieldDeclaration) type.bodyDeclarations().get(count++);
+ checkSourceRange(field, "Object b = new @NonNull(value1 = Math.PI) ArrayList< >() ;", contents);
+ fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ classInstanceCreation = (ClassInstanceCreation) fragment.getInitializer();
+ parameterizedType = (ParameterizedType) classInstanceCreation.getType();
+ checkSourceRange(parameterizedType.getType(), "@NonNull(value1 = Math.PI) ArrayList", contents);
+
+ field = (FieldDeclaration) type.bodyDeclarations().get(count++);
+ checkSourceRange(field, "Object c = new ArrayList<@NonNull(value1= Math.PI ) Object[]>() ;", contents);
+ fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ classInstanceCreation = (ClassInstanceCreation) fragment.getInitializer();
+ parameterizedType = (ParameterizedType) classInstanceCreation.getType();
+ arrayType = (ArrayType) parameterizedType.typeArguments().get(0);
+ assertTrue(arrayType.getDimensions() == 1);
+
+ MethodDeclaration method = (MethodDeclaration) type.bodyDeclarations().get(count++);
+ extraDimension = (ExtraDimension) method.extraDimensions().get(0);
+ checkSourceRange(extraDimension, "@TakeType(int[].class) []", contents);
+ singleMemberAnnotation = (SingleMemberAnnotation) extraDimension.annotations().get(0);
+ typeLiteral = (TypeLiteral) singleMemberAnnotation.getValue();
+ arrayType = (ArrayType) typeLiteral.getType();
+ assertTrue(arrayType.getElementType().isPrimitiveType());
+ assertTrue(arrayType.getDimensions() == 1);
+ SingleVariableDeclaration singleVariableDeclaration = (SingleVariableDeclaration) method.parameters().get(0);
+ singleMemberAnnotation = (SingleMemberAnnotation) singleVariableDeclaration.modifiers().get(0);
+ checkSourceRange(singleMemberAnnotation, "@TakeType(int[].class)", contents);
+ typeLiteral = (TypeLiteral) singleMemberAnnotation.getValue();
+ arrayType = (ArrayType) typeLiteral.getType();
+ assertTrue(arrayType.getElementType().isPrimitiveType());
+ assertTrue(arrayType.getDimensions() == 1);
+ ForStatement forStatement = (ForStatement) method.getBody().statements().get(1);
+ VariableDeclarationExpression variableDeclarationExpression = (VariableDeclarationExpression) forStatement.initializers().get(0);
+ fragment = (VariableDeclarationFragment) variableDeclarationExpression.fragments().get(0);
+ extraDimension = (ExtraDimension) fragment.extraDimensions().get(0);
+ checkSourceRange(extraDimension, "@TakeType(int[].class) []", contents);
+ forStatement = (ForStatement) method.getBody().statements().get(1);
+ variableDeclarationExpression = (VariableDeclarationExpression) forStatement.initializers().get(0);
+ fragment = (VariableDeclarationFragment) variableDeclarationExpression.fragments().get(0);
+ extraDimension = (ExtraDimension) fragment.extraDimensions().get(0);
+ checkSourceRange(extraDimension, "@TakeType(int[].class) []", contents);
+
+ method = (MethodDeclaration) type.bodyDeclarations().get(count++);
+ singleVariableDeclaration = (SingleVariableDeclaration) method.parameters().get(0);
+ // test case active only after bug 417660 is fixed (uncomment)
+ checkSourceRange(singleVariableDeclaration, "int [] /*@TakeType(int[].class)*/ [] a", contents);
+
+ method = (MethodDeclaration) type.bodyDeclarations().get(count++);
+ singleVariableDeclaration = (SingleVariableDeclaration) method.parameters().get(0);
+ checkSourceRange(singleVariableDeclaration, "int @TakeType(int[].class)... args", contents);
+ singleMemberAnnotation = (SingleMemberAnnotation) singleVariableDeclaration.varargsAnnotations().get(0);
+ typeLiteral = (TypeLiteral) singleMemberAnnotation.getValue();
+ arrayType = (ArrayType) typeLiteral.getType();
+ assertTrue(arrayType.getElementType().isPrimitiveType());
+ assertTrue(arrayType.getDimensions() == 1);
+
+ method = (MethodDeclaration) type.bodyDeclarations().get(count++);
+ singleVariableDeclaration = (SingleVariableDeclaration) method.parameters().get(0);
+ checkSourceRange(singleVariableDeclaration, "int @Annot ... args", contents);
+ assertTrue(singleVariableDeclaration.varargsAnnotations().size() == 1);
+
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=409586
+ public void testBug409586() throws JavaModelException {
+ String contents =
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {\n" +
+ " String value() default \"\";\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {\n" +
+ " String value() default \"22\";\n" +
+ "}\n" +
+ "public class X {\n" +
+ " public @Marker(\"1\") String foo(int @Marker @Marker2 [] args) {\n" +
+ " return null;\n" +
+ " }\n" +
+ " public @Marker(\"3\") String bar() {\n" +
+ " return null;\n" +
+ " }\n" +
+ " public String @Marker(\"i0\") @Marker2 [] [] @Marker(\"i1\") [] str = null;\n" +
+ " public @Marker String str2 = null;\n" +
+ " public @Marker String str3 = null;\n" +
+ " public String str4 = null;\n" +
+ "}";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ node = getASTNode(compilationUnit, 2, 0);
+ assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION);
+ MethodDeclaration methodDeclaration = (MethodDeclaration) node;
+ IMethodBinding mBinding = methodDeclaration.resolveBinding();
+ assertNotNull("Should not be null", mBinding);
+ ITypeBinding tBinding1 = mBinding.getReturnType();
+ assertNotNull("Should not be null", tBinding1);
+
+ List params = methodDeclaration.parameters();
+ assertEquals("Incorrect params", 1, params.size());
+ SingleVariableDeclaration param = (SingleVariableDeclaration) params.get(0);
+ ArrayType type = (ArrayType) param.getType();
+ ITypeBinding tBinding = type.resolveBinding();
+ assertNotNull("Should not be null", tBinding);
+ IAnnotationBinding[] annots = tBinding.getTypeAnnotations();
+ assertEquals("Incorrect type annotations", 2, annots.length);
+ assertEquals("Incorrect annotation", "@Marker()", annots[0].toString());
+ assertEquals("Incorrect annotation", "@Marker2()", annots[1].toString());
+
+ node = getASTNode(compilationUnit, 2, 1);
+ assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION);
+ methodDeclaration = (MethodDeclaration) node;
+ mBinding = methodDeclaration.resolveBinding();
+ assertNotNull("Should not be null", mBinding);
+ ITypeBinding tBinding2 = mBinding.getReturnType();
+ assertNotNull("Should not be null", tBinding1);
+ assertNotSame("Type bindings should not be same", tBinding1, tBinding2);
+ annots = tBinding1.getTypeAnnotations();
+ assertEquals("Incorrect type annotations", 1, annots.length);
+ IAnnotationBinding annot = annots[0];
+ assertEquals("Incorrect annotation", "@Marker(value = 1)", annot.toString());
+ annots = tBinding2.getTypeAnnotations();
+ assertEquals("Incorrect type annotations", 1, annots.length);
+ annot = annots[0];
+ assertEquals("Incorrect annotation", "@Marker(value = 3)", annot.toString());
+
+ node = getASTNode(compilationUnit, 2, 2);
+ assertTrue("Not a field declaration", node.getNodeType() == ASTNode.FIELD_DECLARATION);
+ FieldDeclaration field = (FieldDeclaration) node;
+ List fragments = field.fragments();
+ assertEquals("Incorrect no of fragments", 1, fragments.size());
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0);
+ IVariableBinding variable = fragment.resolveBinding();
+ assertNotNull("Should not be null", variable);
+ ITypeBinding tBinding3 = variable.getType();
+ assertNotNull("Should not be null", tBinding3);
+ annots = tBinding3.getTypeAnnotations();
+
+ assertEquals("Incorrect type annotations", 2, annots.length);
+ assertEquals("Incorrect annotation", "@Marker(value = i0)", annots[0].toString());
+ assertEquals("Incorrect annotation", "@Marker2()", annots[1].toString());
+ tBinding3 = tBinding3.getComponentType();
+ annots = tBinding3.getTypeAnnotations();
+ assertEquals("Incorrect type annotations", 0, annots.length);
+ tBinding3 = tBinding3.getComponentType();
+ annots = tBinding3.getTypeAnnotations();
+ assertEquals("Incorrect type annotations", 1, annots.length);
+ assertEquals("Incorrect annotation", "@Marker(value = i1)", annots[0].toString());
+
+ node = getASTNode(compilationUnit, 2, 3);
+ assertTrue("Not a field declaration", node.getNodeType() == ASTNode.FIELD_DECLARATION);
+ field = (FieldDeclaration) node;
+ fragments = field.fragments();
+ assertEquals("Incorrect no of fragments", 1, fragments.size());
+ fragment = (VariableDeclarationFragment) fragments.get(0);
+ variable = fragment.resolveBinding();
+ assertNotNull("Should not be null", variable);
+ tBinding1 = variable.getType();
+
+ node = getASTNode(compilationUnit, 2, 4);
+ assertTrue("Not a field declaration", node.getNodeType() == ASTNode.FIELD_DECLARATION);
+ field = (FieldDeclaration) node;
+ fragments = field.fragments();
+ assertEquals("Incorrect no of fragments", 1, fragments.size());
+ fragment = (VariableDeclarationFragment) fragments.get(0);
+ variable = fragment.resolveBinding();
+ assertNotNull("Should not be null", variable);
+ tBinding2 = variable.getType();
+ assertSame("Type bindings should be same", tBinding1, tBinding2);
+ assertTrue("Unannotated bindings should be same", tBinding1.isEqualTo(tBinding2));
+
+ node = getASTNode(compilationUnit, 2, 5);
+ assertTrue("Not a field declaration", node.getNodeType() == ASTNode.FIELD_DECLARATION);
+ field = (FieldDeclaration) node;
+ fragments = field.fragments();
+ assertEquals("Incorrect no of fragments", 1, fragments.size());
+ fragment = (VariableDeclarationFragment) fragments.get(0);
+ variable = fragment.resolveBinding();
+ assertNotNull("Should not be null", variable);
+ tBinding2 = variable.getType();
+ assertNotSame("Type bindings should not be same", tBinding1, tBinding2);
+ assertTrue("Unannotated bindings should be same", tBinding1.isEqualTo(tBinding2));
+ }
+
+ public void testExtendedDimensions() throws JavaModelException {
+ String contents =
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {\n" +
+ " String value() default \"\";\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {\n" +
+ " String value() default \"22\";\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker3 {\n" +
+ " String value() default \"22\";\n" +
+ "}\n" +
+ "public class X {\n" +
+ " public @Marker(\"1\") String @Marker(\"2\") [] foo(int @Marker @Marker2 [] args @Marker3 []) @Marker3(\"3\") [] {\n" +
+ " return null;\n" +
+ " }\n" +
+ " public String @Marker(\"i0\") @Marker2 [] [] @Marker(\"i1\") [] str @Marker(\"Extended\") [] = null;\n" +
+ "}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ node = getASTNode(compilationUnit, 3, 0);
+ assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION);
+ MethodDeclaration methodDeclaration = (MethodDeclaration) node;
+ Type returnType = methodDeclaration.getReturnType2();
+ ITypeBinding tBinding1 = returnType.resolveBinding();
+ assertEquals("Unexpected type", tBinding1.toString(), "@Marker{ value = (String)\"1\"} String @Marker{ value = (String)\"2\"} []");
+ assertEquals("Unexpected type", methodDeclaration.resolveBinding().getReturnType().toString(), "@Marker{ value = (String)\"1\"} String @Marker3{ value = (String)\"3\"} [] @Marker{ value = (String)\"2\"} []");
+
+ List params = methodDeclaration.parameters();
+ assertEquals("Incorrect params", 1, params.size());
+ SingleVariableDeclaration param = (SingleVariableDeclaration) params.get(0);
+ ArrayType type = (ArrayType) param.getType();
+ ITypeBinding tBinding = type.resolveBinding();
+ assertEquals("Unexpected type", tBinding.toString(), "int @Marker @Marker2 []");
+ assertEquals("Unexpected type", param.resolveBinding().getType().toString(), "int @Marker3 [] @Marker @Marker2 []");
+
+ // public String @Marker(\"i0\") @Marker2 [] [] @Marker(\"i1\") [] str @Marker(\"Extended\") [] = null;
+ node = getASTNode(compilationUnit, 3, 1);
+ assertTrue("Not a field declaration", node.getNodeType() == ASTNode.FIELD_DECLARATION);
+ FieldDeclaration field = (FieldDeclaration) node;
+ List fragments = field.fragments();
+ assertEquals("Incorrect no of fragments", 1, fragments.size());
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0);
+ assertEquals("Unexpected type", fragment.resolveBinding().getType().toString(), "String @Marker{ value = (String)\"Extended\"} [] @Marker{ value = (String)\"i0\"} @Marker2 [] [] @Marker{ value = (String)\"i1\"} []");
+ assertEquals("Unexpected type", field.getType().toString(), "String @Marker(\"i0\") @Marker2 [] [] @Marker(\"i1\") []");
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=417669
+ public void testBug417669() throws JavaModelException {
+ String contents =
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "public class X {\n" +
+ " public static void main(String [] args) {\n" +
+ " W<String> w = (@Marker W<String>) null;\n" +
+ " }\n" +
+ "}\n" +
+ "class W<T> {}";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ node = getASTNode(compilationUnit, 1, 0);
+ assertTrue("Not a method declaration", node.getNodeType() == ASTNode.METHOD_DECLARATION);
+ MethodDeclaration method = (MethodDeclaration) node;
+ assertEquals("Method should not be malformed", 0, (method.getFlags() & ASTNode.MALFORMED));
+
+ List statements = method.getBody().statements();
+ VariableDeclarationStatement statement = (VariableDeclarationStatement) statements.get(0);
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) statement.fragments().get(0);
+ CastExpression cast = (CastExpression) fragment.getInitializer();
+ ParameterizedType castType = (ParameterizedType) cast.getType();
+ Type type = castType.getType();
+ checkSourceRange(castType, "@Marker W<String>", contents);
+ checkSourceRange(type, "@Marker W", contents);
+ }
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java
index 9d77f72f8..a62bafd22 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST3Test.java
@@ -59,6 +59,13 @@ public class ASTConverterAST3Test extends ConverterTestSetup {
return methodDeclaration.thrownExceptions();
}
+ /**
+ * @deprecated
+ */
+ private Type componentType(ArrayType array) {
+ return array.getComponentType();
+ }
+
public void test0001() throws JavaModelException {
ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0001", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
char[] source = sourceUnit.getSource().toCharArray();
@@ -7659,13 +7666,13 @@ public class ASTConverterAST3Test extends ConverterTestSetup {
ITypeBinding typeBinding = arrayType.resolveBinding();
checkSourceRange(type, "java.lang.Object[][]", source); //$NON-NLS-1$
assertNotNull("No type binding", typeBinding); //$NON-NLS-1$
- Type elementType = arrayType.getComponentType();
+ Type elementType = componentType(arrayType);
ITypeBinding typeBinding2 = elementType.resolveBinding();
assertNotNull("No type binding2", typeBinding2); //$NON-NLS-1$
assertEquals("wrong dimension", 1, typeBinding2.getDimensions()); //$NON-NLS-1$
assertEquals("wrong name", "Object[]", typeBinding2.getName()); //$NON-NLS-1$ //$NON-NLS-2$
assertTrue("Not an array type", elementType.isArrayType()); //$NON-NLS-1$
- Type elementType2 = ((ArrayType) elementType).getComponentType();
+ Type elementType2 = componentType(((ArrayType) elementType));
assertTrue("Not a simple type", elementType2.isSimpleType()); //$NON-NLS-1$
ITypeBinding typeBinding3 = elementType2.resolveBinding();
assertNotNull("No type binding3", typeBinding3); //$NON-NLS-1$
@@ -8006,7 +8013,7 @@ public class ASTConverterAST3Test extends ConverterTestSetup {
ITypeBinding typeBinding3 = simpleType.resolveBinding();
assertNotNull("no type binding3", typeBinding3); //$NON-NLS-1$
assertEquals("wrong name", "Object", typeBinding3.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
assertTrue("Not an array type", type instanceof ArrayType); //$NON-NLS-1$
ArrayType arrayType2 = (ArrayType) type;
ITypeBinding typeBinding4 = arrayType2.resolveBinding();
@@ -8048,14 +8055,14 @@ public class ASTConverterAST3Test extends ConverterTestSetup {
ITypeBinding typeBinding3 = simpleType.resolveBinding();
assertNotNull("no type binding3", typeBinding3); //$NON-NLS-1$
assertEquals("wrong name", "Object", typeBinding3.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
assertTrue("Not an array type", type instanceof ArrayType); //$NON-NLS-1$
ArrayType arrayType2 = (ArrayType) type;
checkSourceRange(arrayType2, "Object[10][]", source); //$NON-NLS-1$
ITypeBinding typeBinding4 = arrayType2.resolveBinding();
assertNotNull("no type binding4", typeBinding4); //$NON-NLS-1$
assertEquals("wrong name", "Object[][]", typeBinding4.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- type = arrayType2.getComponentType();
+ type = componentType(arrayType2);
assertTrue("Not an array type", type instanceof ArrayType); //$NON-NLS-1$
ArrayType arrayType3 = (ArrayType) type;
ITypeBinding typeBinding5 = arrayType3.resolveBinding();
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java
index 8f41012bf..c58a21833 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST4Test.java
@@ -59,6 +59,13 @@ public class ASTConverterAST4Test extends ConverterTestSetup {
return methodDeclaration.thrownExceptions();
}
+ /**
+ * @deprecated
+ */
+ private Type componentType(ArrayType array) {
+ return array.getComponentType();
+ }
+
public void test0001() throws JavaModelException {
ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0001", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
char[] source = sourceUnit.getSource().toCharArray();
@@ -7659,13 +7666,13 @@ public class ASTConverterAST4Test extends ConverterTestSetup {
ITypeBinding typeBinding = arrayType.resolveBinding();
checkSourceRange(type, "java.lang.Object[][]", source); //$NON-NLS-1$
assertNotNull("No type binding", typeBinding); //$NON-NLS-1$
- Type elementType = arrayType.getComponentType();
+ Type elementType = componentType(arrayType);
ITypeBinding typeBinding2 = elementType.resolveBinding();
assertNotNull("No type binding2", typeBinding2); //$NON-NLS-1$
assertEquals("wrong dimension", 1, typeBinding2.getDimensions()); //$NON-NLS-1$
assertEquals("wrong name", "Object[]", typeBinding2.getName()); //$NON-NLS-1$ //$NON-NLS-2$
assertTrue("Not an array type", elementType.isArrayType()); //$NON-NLS-1$
- Type elementType2 = ((ArrayType) elementType).getComponentType();
+ Type elementType2 = componentType(((ArrayType) elementType));
assertTrue("Not a simple type", elementType2.isSimpleType()); //$NON-NLS-1$
ITypeBinding typeBinding3 = elementType2.resolveBinding();
assertNotNull("No type binding3", typeBinding3); //$NON-NLS-1$
@@ -8006,7 +8013,7 @@ public class ASTConverterAST4Test extends ConverterTestSetup {
ITypeBinding typeBinding3 = simpleType.resolveBinding();
assertNotNull("no type binding3", typeBinding3); //$NON-NLS-1$
assertEquals("wrong name", "Object", typeBinding3.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
assertTrue("Not an array type", type instanceof ArrayType); //$NON-NLS-1$
ArrayType arrayType2 = (ArrayType) type;
ITypeBinding typeBinding4 = arrayType2.resolveBinding();
@@ -8048,14 +8055,14 @@ public class ASTConverterAST4Test extends ConverterTestSetup {
ITypeBinding typeBinding3 = simpleType.resolveBinding();
assertNotNull("no type binding3", typeBinding3); //$NON-NLS-1$
assertEquals("wrong name", "Object", typeBinding3.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
assertTrue("Not an array type", type instanceof ArrayType); //$NON-NLS-1$
ArrayType arrayType2 = (ArrayType) type;
checkSourceRange(arrayType2, "Object[10][]", source); //$NON-NLS-1$
ITypeBinding typeBinding4 = arrayType2.resolveBinding();
assertNotNull("no type binding4", typeBinding4); //$NON-NLS-1$
assertEquals("wrong name", "Object[][]", typeBinding4.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- type = arrayType2.getComponentType();
+ type = componentType(arrayType2);
assertTrue("Not an array type", type instanceof ArrayType); //$NON-NLS-1$
ArrayType arrayType3 = (ArrayType) type;
ITypeBinding typeBinding5 = arrayType3.resolveBinding();
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java
index ce0fcc42a..d4130e51e 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterAST8Test.java
@@ -7662,15 +7662,9 @@ public class ASTConverterAST8Test extends ConverterTestSetup {
ITypeBinding typeBinding = arrayType.resolveBinding();
checkSourceRange(type, "java.lang.Object[][]", source); //$NON-NLS-1$
assertNotNull("No type binding", typeBinding); //$NON-NLS-1$
- Type elementType = arrayType.getComponentType();
- ITypeBinding typeBinding2 = elementType.resolveBinding();
- assertNotNull("No type binding2", typeBinding2); //$NON-NLS-1$
- assertEquals("wrong dimension", 1, typeBinding2.getDimensions()); //$NON-NLS-1$
- assertEquals("wrong name", "Object[]", typeBinding2.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- assertTrue("Not an array type", elementType.isArrayType()); //$NON-NLS-1$
- Type elementType2 = ((ArrayType) elementType).getComponentType();
- assertTrue("Not a simple type", elementType2.isSimpleType()); //$NON-NLS-1$
- ITypeBinding typeBinding3 = elementType2.resolveBinding();
+ Type elementType = arrayType.getElementType();
+ assertTrue("Not a simple type", elementType.isSimpleType()); //$NON-NLS-1$
+ ITypeBinding typeBinding3 = elementType.resolveBinding();
assertNotNull("No type binding3", typeBinding3); //$NON-NLS-1$
assertEquals("wrong dimension", 0, typeBinding3.getDimensions()); //$NON-NLS-1$
assertEquals("wrong name", "Object", typeBinding3.getName()); //$NON-NLS-1$ //$NON-NLS-2$
@@ -8009,12 +8003,10 @@ public class ASTConverterAST8Test extends ConverterTestSetup {
ITypeBinding typeBinding3 = simpleType.resolveBinding();
assertNotNull("no type binding3", typeBinding3); //$NON-NLS-1$
assertEquals("wrong name", "Object", typeBinding3.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- type = arrayType.getComponentType();
- assertTrue("Not an array type", type instanceof ArrayType); //$NON-NLS-1$
- ArrayType arrayType2 = (ArrayType) type;
- ITypeBinding typeBinding4 = arrayType2.resolveBinding();
+ type = arrayType.getElementType();
+ ITypeBinding typeBinding4 = type.resolveBinding();
assertNotNull("no type binding4", typeBinding4); //$NON-NLS-1$
- assertEquals("wrong name", "Object[]", typeBinding4.getName()); //$NON-NLS-1$ //$NON-NLS-2$
+ assertEquals("wrong name", "Object", typeBinding4.getName()); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
@@ -8051,20 +8043,10 @@ public class ASTConverterAST8Test extends ConverterTestSetup {
ITypeBinding typeBinding3 = simpleType.resolveBinding();
assertNotNull("no type binding3", typeBinding3); //$NON-NLS-1$
assertEquals("wrong name", "Object", typeBinding3.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- type = arrayType.getComponentType();
- assertTrue("Not an array type", type instanceof ArrayType); //$NON-NLS-1$
- ArrayType arrayType2 = (ArrayType) type;
- checkSourceRange(arrayType2, "Object[10][]", source); //$NON-NLS-1$
- ITypeBinding typeBinding4 = arrayType2.resolveBinding();
+ type = arrayType.getElementType();
+ ITypeBinding typeBinding4 = type.resolveBinding();
assertNotNull("no type binding4", typeBinding4); //$NON-NLS-1$
- assertEquals("wrong name", "Object[][]", typeBinding4.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- type = arrayType2.getComponentType();
- assertTrue("Not an array type", type instanceof ArrayType); //$NON-NLS-1$
- ArrayType arrayType3 = (ArrayType) type;
- ITypeBinding typeBinding5 = arrayType3.resolveBinding();
- assertNotNull("no type binding5", typeBinding5); //$NON-NLS-1$
- assertEquals("wrong name", "Object[]", typeBinding5.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- checkSourceRange(arrayType3, "Object[10]", source); //$NON-NLS-1$
+ assertEquals("wrong name", "Object", typeBinding4.getName()); //$NON-NLS-1$ //$NON-NLS-2$
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocFlattener.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocFlattener.java
index d58dbdcd6..3f396b9c9 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocFlattener.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterJavadocFlattener.java
@@ -1,10 +1,14 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 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
*******************************************************************************/
@@ -33,6 +37,13 @@ ASTConverterJavadocFlattener(String comment) {
}
/**
+ * @deprecated
+ */
+private Type componentType(ArrayType array) {
+ return array.getComponentType();
+}
+
+/**
* Returns the string accumulated in the visit.
*
* @return the serialized
@@ -52,8 +63,15 @@ public void reset() {
* @see ASTVisitor#visit(ArrayType)
*/
public boolean visit(ArrayType node) {
- node.getComponentType().accept(this);
- this.buffer.append("[]");//$NON-NLS-1$
+ if (node.getAST().apiLevel() < AST.JLS8) {
+ componentType(node).accept(this);
+ this.buffer.append("[]");//$NON-NLS-1$
+ } else {
+ node.getElementType().accept(this);
+ for (int i = 0; i < node.getDimensions(); ++i) {
+ ((ExtraDimension) node.dimensions().get(i)).accept(this);
+ }
+ }
return false;
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java
index 8d60553d0..ac6c02c37 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest.java
@@ -52,6 +52,13 @@ public class ASTConverterTest extends ConverterTestSetup {
return methodDeclaration.thrownExceptions();
}
+ /**
+ * @deprecated
+ */
+ private Type componentType(ArrayType array) {
+ return array.getComponentType();
+ }
+
/** @deprecated using deprecated code */
public void test0001() throws JavaModelException {
ICompilationUnit sourceUnit = getCompilationUnit("Converter" , "src", "test0001", "Test.java"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
@@ -7821,13 +7828,13 @@ public class ASTConverterTest extends ConverterTestSetup {
ITypeBinding typeBinding = arrayType.resolveBinding();
checkSourceRange(type, "java.lang.Object[][]", source); //$NON-NLS-1$
assertNotNull("No type binding", typeBinding); //$NON-NLS-1$
- Type elementType = arrayType.getComponentType();
+ Type elementType = componentType(arrayType);
ITypeBinding typeBinding2 = elementType.resolveBinding();
assertNotNull("No type binding2", typeBinding2); //$NON-NLS-1$
assertEquals("wrong dimension", 1, typeBinding2.getDimensions()); //$NON-NLS-1$
assertEquals("wrong name", "Object[]", typeBinding2.getName()); //$NON-NLS-1$ //$NON-NLS-2$
assertTrue("Not an array type", elementType.isArrayType()); //$NON-NLS-1$
- Type elementType2 = ((ArrayType) elementType).getComponentType();
+ Type elementType2 = componentType(((ArrayType) elementType));
assertTrue("Not a simple type", elementType2.isSimpleType()); //$NON-NLS-1$
ITypeBinding typeBinding3 = elementType2.resolveBinding();
assertNotNull("No type binding3", typeBinding3); //$NON-NLS-1$
@@ -8168,7 +8175,7 @@ public class ASTConverterTest extends ConverterTestSetup {
ITypeBinding typeBinding3 = simpleType.resolveBinding();
assertNotNull("no type binding3", typeBinding3); //$NON-NLS-1$
assertEquals("wrong name", "Object", typeBinding3.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
assertTrue("Not an array type", type instanceof ArrayType); //$NON-NLS-1$
ArrayType arrayType2 = (ArrayType) type;
ITypeBinding typeBinding4 = arrayType2.resolveBinding();
@@ -8210,14 +8217,14 @@ public class ASTConverterTest extends ConverterTestSetup {
ITypeBinding typeBinding3 = simpleType.resolveBinding();
assertNotNull("no type binding3", typeBinding3); //$NON-NLS-1$
assertEquals("wrong name", "Object", typeBinding3.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- type = arrayType.getComponentType();
+ type = componentType(arrayType);
assertTrue("Not an array type", type instanceof ArrayType); //$NON-NLS-1$
ArrayType arrayType2 = (ArrayType) type;
checkSourceRange(arrayType2, "Object[10][]", source); //$NON-NLS-1$
ITypeBinding typeBinding4 = arrayType2.resolveBinding();
assertNotNull("no type binding4", typeBinding4); //$NON-NLS-1$
assertEquals("wrong name", "Object[][]", typeBinding4.getName()); //$NON-NLS-1$ //$NON-NLS-2$
- type = arrayType2.getComponentType();
+ type = componentType(arrayType2);
assertTrue("Not an array type", type instanceof ArrayType); //$NON-NLS-1$
ArrayType arrayType3 = (ArrayType) type;
ITypeBinding typeBinding5 = arrayType3.resolveBinding();
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest2.java
index 12ad56061..6617fbbb1 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTest2.java
@@ -4,6 +4,10 @@
* 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
@@ -57,6 +61,13 @@ public class ASTConverterTest2 extends ConverterTestSetup {
}
/**
+ * @deprecated
+ */
+ private Type componentType(ArrayType array) {
+ return array.getComponentType();
+ }
+
+ /**
* http://dev.eclipse.org/bugs/show_bug.cgi?id=22560
* @deprecated using deprecated code
*/
@@ -2631,11 +2642,11 @@ public class ASTConverterTest2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
}
@@ -2657,15 +2668,15 @@ public class ASTConverterTest2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[][]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
}
@@ -2687,11 +2698,11 @@ public class ASTConverterTest2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
List fragments = fieldDeclaration.fragments();
@@ -2717,19 +2728,19 @@ public class ASTConverterTest2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][][][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[][][]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[][]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
}
@@ -2751,7 +2762,7 @@ public class ASTConverterTest2 extends ConverterTestSetup {
checkSourceRange(type, "Class[]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java
index 0b9a1772a..7b49755b9 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST3_2.java
@@ -143,6 +143,13 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup {
}
/**
+ * @deprecated
+ */
+ private Type componentType(ArrayType array) {
+ return array.getComponentType();
+ }
+
+ /**
* http://dev.eclipse.org/bugs/show_bug.cgi?id=22560
*/
public void test0401() throws JavaModelException {
@@ -2718,11 +2725,11 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
}
@@ -2744,15 +2751,15 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[][]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
}
@@ -2774,11 +2781,11 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
List fragments = fieldDeclaration.fragments();
@@ -2804,19 +2811,19 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][][][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[][][]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[][]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
}
@@ -2838,7 +2845,7 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
}
@@ -6549,7 +6556,7 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup {
checkSourceRange(type, "boolean[]", contents);
assertTrue("Not an array type", type.isArrayType());
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("Not a primitive type", componentType.isPrimitiveType());
PrimitiveType primitiveType = (PrimitiveType) componentType;
assertEquals("Not boolean", PrimitiveType.BOOLEAN, primitiveType.getPrimitiveTypeCode());
@@ -9541,11 +9548,11 @@ public class ASTConverterTestAST3_2 extends ConverterTestSetup {
ArrayCreation arrayCreation = (ArrayCreation) node;
ArrayType arrayType = arrayCreation.getType();
checkSourceRange(arrayType, "String[0][b[10]][]", sourceUnit.getSource());
- node = arrayType.getComponentType();
+ node = componentType(arrayType);
assertEquals("Not an array type", ASTNode.ARRAY_TYPE, node.getNodeType());
arrayType = (ArrayType)node;
checkSourceRange(arrayType, "String[0][b[10]]", sourceUnit.getSource());
- node = arrayType.getComponentType();
+ node = componentType(arrayType);
assertEquals("Not an array type", ASTNode.ARRAY_TYPE, node.getNodeType());
arrayType = (ArrayType)node;
checkSourceRange(arrayType, "String[0]", sourceUnit.getSource());
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST4_2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST4_2.java
index acf08ef71..25f88a852 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST4_2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST4_2.java
@@ -141,6 +141,13 @@ public class ASTConverterTestAST4_2 extends ConverterTestSetup {
}
/**
+ * @deprecated
+ */
+ private Type componentType(ArrayType array) {
+ return array.getComponentType();
+ }
+
+ /**
* http://dev.eclipse.org/bugs/show_bug.cgi?id=22560
*/
public void test0401() throws JavaModelException {
@@ -2716,11 +2723,11 @@ public class ASTConverterTestAST4_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
}
@@ -2742,15 +2749,15 @@ public class ASTConverterTestAST4_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[][]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
}
@@ -2772,11 +2779,11 @@ public class ASTConverterTestAST4_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
List fragments = fieldDeclaration.fragments();
@@ -2802,19 +2809,19 @@ public class ASTConverterTestAST4_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][][][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[][][]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[][]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class[]", source);
arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
+ componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
}
@@ -2836,7 +2843,7 @@ public class ASTConverterTestAST4_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
checkSourceRange(componentType, "Class", source);
}
@@ -6547,7 +6554,7 @@ public class ASTConverterTestAST4_2 extends ConverterTestSetup {
checkSourceRange(type, "boolean[]", contents);
assertTrue("Not an array type", type.isArrayType());
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("Not a primitive type", componentType.isPrimitiveType());
PrimitiveType primitiveType = (PrimitiveType) componentType;
assertEquals("Not boolean", PrimitiveType.BOOLEAN, primitiveType.getPrimitiveTypeCode());
@@ -9539,11 +9546,11 @@ public class ASTConverterTestAST4_2 extends ConverterTestSetup {
ArrayCreation arrayCreation = (ArrayCreation) node;
ArrayType arrayType = arrayCreation.getType();
checkSourceRange(arrayType, "String[0][b[10]][]", sourceUnit.getSource());
- node = arrayType.getComponentType();
+ node = componentType(arrayType);
assertEquals("Not an array type", ASTNode.ARRAY_TYPE, node.getNodeType());
arrayType = (ArrayType)node;
checkSourceRange(arrayType, "String[0][b[10]]", sourceUnit.getSource());
- node = arrayType.getComponentType();
+ node = componentType(arrayType);
assertEquals("Not an array type", ASTNode.ARRAY_TYPE, node.getNodeType());
arrayType = (ArrayType)node;
checkSourceRange(arrayType, "String[0]", sourceUnit.getSource());
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST8_2.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST8_2.java
index fb32e7511..2e74436cc 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST8_2.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverterTestAST8_2.java
@@ -141,6 +141,13 @@ public class ASTConverterTestAST8_2 extends ConverterTestSetup {
}
/**
+ * @deprecated
+ */
+ private Type componentType(ArrayType array) {
+ return array.getComponentType();
+ }
+
+ /**
* http://dev.eclipse.org/bugs/show_bug.cgi?id=22560
*/
public void test0401() throws JavaModelException {
@@ -2725,13 +2732,18 @@ public class ASTConverterTestAST8_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
- assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
- checkSourceRange(componentType, "Class[]", source);
- arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
- assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
- checkSourceRange(componentType, "Class", source);
+ if (this.ast.apiLevel() < AST.JLS8) {
+ Type componentType = componentType(arrayType);
+ assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
+ checkSourceRange(componentType, "Class[]", source);
+ arrayType = (ArrayType) componentType;
+ componentType = componentType(arrayType);
+ assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
+ checkSourceRange(componentType, "Class", source);
+ } else {
+ Type elementType = arrayType.getElementType();
+ checkSourceRange(elementType, "Class", source);
+ }
}
/**
@@ -2751,17 +2763,22 @@ public class ASTConverterTestAST8_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
- assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
- checkSourceRange(componentType, "Class[][]", source);
- arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
- assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
- checkSourceRange(componentType, "Class[]", source);
- arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
- assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
- checkSourceRange(componentType, "Class", source);
+ if (this.ast.apiLevel() < AST.JLS8) {
+ Type componentType = componentType(arrayType);
+ assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
+ checkSourceRange(componentType, "Class[][]", source);
+ arrayType = (ArrayType) componentType;
+ componentType = componentType(arrayType);
+ assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
+ checkSourceRange(componentType, "Class[]", source);
+ arrayType = (ArrayType) componentType;
+ componentType = componentType(arrayType);
+ assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
+ checkSourceRange(componentType, "Class", source);
+ } else {
+ Type elementType = arrayType.getElementType();
+ checkSourceRange(elementType, "Class", source);
+ }
}
/**
@@ -2781,13 +2798,18 @@ public class ASTConverterTestAST8_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
- assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
- checkSourceRange(componentType, "Class[]", source);
- arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
- assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
- checkSourceRange(componentType, "Class", source);
+ if (this.ast.apiLevel() < AST.JLS8) {
+ Type componentType = componentType(arrayType);
+ assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
+ checkSourceRange(componentType, "Class[]", source);
+ arrayType = (ArrayType) componentType;
+ componentType = componentType(arrayType);
+ assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
+ checkSourceRange(componentType, "Class", source);
+ } else {
+ Type elementType = arrayType.getElementType();
+ checkSourceRange(elementType, "Class", source);
+ }
List fragments = fieldDeclaration.fragments();
assertEquals("wrong size", 1, fragments.size());
VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0);
@@ -2811,21 +2833,26 @@ public class ASTConverterTestAST8_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[][][][]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
- assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
- checkSourceRange(componentType, "Class[][][]", source);
- arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
- assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
- checkSourceRange(componentType, "Class[][]", source);
- arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
- assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
- checkSourceRange(componentType, "Class[]", source);
- arrayType = (ArrayType) componentType;
- componentType = arrayType.getComponentType();
- assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
- checkSourceRange(componentType, "Class", source);
+ if (this.ast.apiLevel() < AST.JLS8) {
+ Type componentType = componentType(arrayType);
+ assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
+ checkSourceRange(componentType, "Class[][][]", source);
+ arrayType = (ArrayType) componentType;
+ componentType = componentType(arrayType);
+ assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
+ checkSourceRange(componentType, "Class[][]", source);
+ arrayType = (ArrayType) componentType;
+ componentType = componentType(arrayType);
+ assertTrue("not an array type", componentType.isArrayType()); //$NON-NLS-1$
+ checkSourceRange(componentType, "Class[]", source);
+ arrayType = (ArrayType) componentType;
+ componentType = componentType(arrayType);
+ assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
+ checkSourceRange(componentType, "Class", source);
+ } else {
+ Type elementType = arrayType.getElementType();
+ checkSourceRange(elementType, "Class", source);
+ }
}
/**
@@ -2845,9 +2872,9 @@ public class ASTConverterTestAST8_2 extends ConverterTestSetup {
checkSourceRange(type, "Class[]", source);
assertTrue("not an array type", type.isArrayType()); //$NON-NLS-1$
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
- assertTrue("is an array type", !componentType.isArrayType()); //$NON-NLS-1$
- checkSourceRange(componentType, "Class", source);
+ type = this.ast.apiLevel() < AST.JLS8 ? componentType(arrayType) : arrayType.getElementType();
+ assertTrue("is an array type", !type.isArrayType()); //$NON-NLS-1$
+ checkSourceRange(type, "Class", source);
}
/**
@@ -6556,7 +6583,7 @@ public class ASTConverterTestAST8_2 extends ConverterTestSetup {
checkSourceRange(type, "boolean[]", contents);
assertTrue("Not an array type", type.isArrayType());
ArrayType arrayType = (ArrayType) type;
- Type componentType = arrayType.getComponentType();
+ Type componentType = componentType(arrayType);
assertTrue("Not a primitive type", componentType.isPrimitiveType());
PrimitiveType primitiveType = (PrimitiveType) componentType;
assertEquals("Not boolean", PrimitiveType.BOOLEAN, primitiveType.getPrimitiveTypeCode());
@@ -9548,14 +9575,19 @@ public class ASTConverterTestAST8_2 extends ConverterTestSetup {
ArrayCreation arrayCreation = (ArrayCreation) node;
ArrayType arrayType = arrayCreation.getType();
checkSourceRange(arrayType, "String[0][b[10]][]", sourceUnit.getSource());
- node = arrayType.getComponentType();
- assertEquals("Not an array type", ASTNode.ARRAY_TYPE, node.getNodeType());
- arrayType = (ArrayType)node;
- checkSourceRange(arrayType, "String[0][b[10]]", sourceUnit.getSource());
- node = arrayType.getComponentType();
- assertEquals("Not an array type", ASTNode.ARRAY_TYPE, node.getNodeType());
- arrayType = (ArrayType)node;
- checkSourceRange(arrayType, "String[0]", sourceUnit.getSource());
+ if (this.ast.apiLevel() < AST.JLS8) {
+ node = componentType(arrayType);
+ assertEquals("Not an array type", ASTNode.ARRAY_TYPE, node.getNodeType());
+ arrayType = (ArrayType)node;
+ checkSourceRange(arrayType, "String[0][b[10]]", sourceUnit.getSource());
+ node = componentType(arrayType);
+ assertEquals("Not an array type", ASTNode.ARRAY_TYPE, node.getNodeType());
+ arrayType = (ArrayType)node;
+ checkSourceRange(arrayType, "String[0]", sourceUnit.getSource());
+ } else {
+ node = arrayType.getElementType();
+ checkSourceRange(node, "String", sourceUnit.getSource());
+ }
}
/**
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 68afd18dd..6710c8c71 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
@@ -217,7 +217,7 @@ public class ASTStructuralPropertyTest extends org.eclipse.jdt.core.tests.junit.
break;
case AST.JLS8 :
assertEquals("Wrong number of visited node classes", 84, nodeClasses.size());
- assertEquals("Wrong number of visited properties", 105, visitedProperties.size());
+ assertEquals("Wrong number of visited properties", 106, visitedProperties.size());
//{ObjectTeams: 2 new simple properties in TypeDeclaration: TEAM_PROPERTY and ROLE_PROPERTY:
// 1 new property in ImportDeclaration: BASE_PROPERTY
/* orig:
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 aa3b9a433..3a5a4acda 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
@@ -2067,6 +2067,18 @@ public class ASTTest extends org.eclipse.jdt.core.tests.junit.extension.TestCase
assertTrue(PrimitiveType.toCode("not-a-type") == null); //$NON-NLS-1$
}
+ /**
+ * @deprecated
+ */
+ Type getArrayComponentType(ArrayType array) {
+ return array.getComponentType();
+ }
+ /**
+ * @deprecated
+ */
+ void setArrayComponentType(ArrayType array, Type type) {
+ array.setComponentType(type);
+ }
public void testArrayType() {
SimpleName x1 = this.ast.newSimpleName("String"); //$NON-NLS-1$
SimpleType x2 = this.ast.newSimpleType(x1);
@@ -2076,7 +2088,11 @@ public class ASTTest extends org.eclipse.jdt.core.tests.junit.extension.TestCase
previousCount = this.ast.modificationCount();
assertTrue(x.getAST() == this.ast);
assertTrue(x.getParent() == null);
- assertTrue(x.getComponentType().getParent() == x);
+ if (this.ast.apiLevel() < AST.JLS8) {
+ assertTrue(getArrayComponentType(x).getParent() == x);
+ } else {
+ assertTrue(x.getElementType().getParent() == x);
+ }
// make sure that reading did not change modification count
assertTrue(this.ast.modificationCount() == previousCount);
assertTrue(!x.isSimpleType());
@@ -2091,39 +2107,69 @@ public class ASTTest extends org.eclipse.jdt.core.tests.junit.extension.TestCase
assertTrue(x.getDimensions() == 1);
assertTrue(x.getElementType() == x2);
- genericPropertyTest(x, new Property("ComponentType", true, Type.class) { //$NON-NLS-1$
- public ASTNode sample(AST targetAst, boolean parented) {
- SimpleType result = targetAst.newSimpleType(
- targetAst.newSimpleName("a")); //$NON-NLS-1$
- if (parented) {
- targetAst.newArrayType(result);
+ if (this.ast.apiLevel() < AST.JLS8) {
+ genericPropertyTest(x, new Property("ComponentType", true, Type.class) { //$NON-NLS-1$
+ public ASTNode sample(AST targetAst, boolean parented) {
+ SimpleType result = targetAst.newSimpleType(
+ targetAst.newSimpleName("a")); //$NON-NLS-1$
+ if (parented) {
+ targetAst.newArrayType(result);
+ }
+ return result;
}
- return result;
- }
- public ASTNode wrap() {
- ArrayType result = ASTTest.this.ast.newArrayType(x);
- return result;
- }
- public void unwrap() {
- ArrayType a = (ArrayType) x.getParent();
- a.setComponentType(ASTTest.this.ast.newPrimitiveType(PrimitiveType.INT));
- }
- public ASTNode get() {
- return x.getComponentType();
- }
- public void set(ASTNode value) {
- x.setComponentType((Type) value);
- }
- });
+ public ASTNode wrap() {
+ ArrayType result = ASTTest.this.ast.newArrayType(x);
+ return result;
+ }
+ public void unwrap() {
+ ArrayType a = (ArrayType) x.getParent();
+ setArrayComponentType(a, ASTTest.this.ast.newPrimitiveType(PrimitiveType.INT));
+ }
+ public ASTNode get() {
+ return getArrayComponentType(x);
+ }
+ public void set(ASTNode value) {
+ setArrayComponentType(x, (Type) value);
+ }
+ });
+
+ setArrayComponentType(x,
+ this.ast.newArrayType(this.ast.newPrimitiveType(PrimitiveType.INT), 4));
+ assertTrue(x.getDimensions() == 5);
+ assertTrue(x.getElementType().isPrimitiveType());
+ final ArrayType x3 = this.ast.newArrayType(x, 2);
+ assertTrue(x3.getDimensions() == 7);
+ } else {
+ genericPropertyTest(x, new Property("ElementType", true, Type.class) { //$NON-NLS-1$
+ public ASTNode sample(AST targetAst, boolean parented) {
+ SimpleType result = targetAst.newSimpleType(
+ targetAst.newSimpleName("a")); //$NON-NLS-1$
+ if (parented) {
+ targetAst.newArrayType(result);
+ }
+ return result;
+ }
+ public ASTNode wrap() {
+ ArrayType result = ASTTest.this.ast.newArrayType(x, 5);
+ return result;
+ }
+ public void unwrap() {
+ ArrayType a = (ArrayType) x.getParent();
+ a.setElementType(ASTTest.this.ast.newPrimitiveType(PrimitiveType.INT));
+ }
+ public ASTNode get() {
+ return x.getElementType();
+ }
+ public void set(ASTNode value) {
+ x.setElementType((Type) value);
+ }
+ });
- x.setComponentType(
- this.ast.newArrayType(this.ast.newPrimitiveType(PrimitiveType.INT), 4));
+ x.setElementType(this.ast.newPrimitiveType(PrimitiveType.INT));
+ assertTrue(x.getDimensions() == 1);
+ assertTrue(x.getElementType().isPrimitiveType());
+ }
- assertTrue(x.getDimensions() == 5);
- assertTrue(x.getElementType().isPrimitiveType());
- final ArrayType x3 = this.ast.newArrayType(x, 2);
- assertTrue(x3.getDimensions() == 7);
-
try {
this.ast.newArrayType(null, 2);
} catch(IllegalArgumentException e) {
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 a94cb24b8..076d46ae8 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
@@ -1157,7 +1157,8 @@ public class ASTVisitorTest extends org.eclipse.jdt.core.tests.junit.extension.T
this.b.setLength(0);
x1.accept(v1);
String result = this.b.toString();
- assertTrue("[(tA[(tPcharchartP)]tA)]".equals(result)); //$NON-NLS-1$
+ String expected = this.ast.apiLevel() < AST.JLS8 ? "[(tA[(tPcharchartP)]tA)]" : "[(tA[(tPcharchartP)][(@ED@ED)]tA)]";
+ assertTrue(expected.equals(result)); //$NON-NLS-1$
}
/** @deprecated using deprecated code */
@@ -1254,7 +1255,8 @@ public class ASTVisitorTest extends org.eclipse.jdt.core.tests.junit.extension.T
this.b.setLength(0);
x1.accept(v1);
String result = this.b.toString();
- assertTrue(result.equals("[(eAC"+"[(tA"+this.T1S+"tA)]"+this.E1S+this.E2S+"[(eAIeAI)]eAC)]")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ String dim = this.ast.apiLevel() < AST.JLS8 ? "" : "[(@ED@ED)]";
+ assertTrue(result.equals("[(eAC"+"[(tA"+this.T1S+ dim +"tA)]"+this.E1S+this.E2S+"[(eAIeAI)]eAC)]")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
public void testArrayInitializer() {
ArrayInitializer x1 = this.ast.newArrayInitializer();
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeAnnotationsConverterTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeAnnotationsConverterTest.java
index 1ca0cb33b..c7efeb04b 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeAnnotationsConverterTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeAnnotationsConverterTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 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
@@ -162,7 +162,7 @@ public class TypeAnnotationsConverterTest extends ConverterTestSetup {
"class Z<Q> {\n" +
" }\n" +
" }\n" +
- " Object o=(@Marker X<@Marker String>.@Marker Y<@Marker Integer>.@Marker Z<@Marker Object>@Marker [][]@Marker [][])null;\n" +
+ " Object o=(@Marker X<@Marker String>.@Marker Y<@Marker Integer>.@Marker Z<@Marker Object> @Marker [] [] @Marker [] [])null;\n" +
" @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface Marker {}\n" +
"}\n";
assertASTNodeEquals(expectedOutput, node);
@@ -191,7 +191,7 @@ public class TypeAnnotationsConverterTest extends ConverterTestSetup {
"class Z<Q> {\n" +
" }\n" +
" }\n" +
- " Object o=(@Marker X<@Marker String>.@Marker Y<@Marker Integer>.@Marker Z<@Marker Object>[]@Marker [][]@Marker [])null;\n" +
+ " Object o=(@Marker X<@Marker String>.@Marker Y<@Marker Integer>.@Marker Z<@Marker Object> [] @Marker [] [] @Marker [])null;\n" +
" @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface Marker {}\n" +
"}\n";
assertASTNodeEquals(expectedOutput, node);
@@ -220,7 +220,7 @@ public class TypeAnnotationsConverterTest extends ConverterTestSetup {
"class Z<Q> {\n" +
" }\n" +
" }\n" +
- " int[][][][] o=(@One int[]@Two [][]@Three [])null;\n" +
+ " int [] [] [] [] o=(@One int [] @Two [] [] @Three [])null;\n" +
" @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface Marker {}\n" +
"}\n";
assertASTNodeEquals(expectedOutput, node);
@@ -249,7 +249,7 @@ public class TypeAnnotationsConverterTest extends ConverterTestSetup {
"class Z<Q> {\n" +
" }\n" +
" }\n" +
- " String[][][][] o=(@One String[]@Two [][]@Three [])null;\n" +
+ " String [] [] [] [] o=(@One String [] @Two [] [] @Three [])null;\n" +
" @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface Marker {}\n" +
"}\n";
assertASTNodeEquals(expectedOutput, node);
@@ -278,7 +278,7 @@ public class TypeAnnotationsConverterTest extends ConverterTestSetup {
"class Z<Q> {\n" +
" }\n" +
" }\n" +
- " Object o=(@One X<String>[]@Two [][]@Three [])null;\n" +
+ " Object o=(@One X<String> [] @Two [] [] @Three [])null;\n" +
" @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) @interface Marker {}\n" +
"}\n";
assertASTNodeEquals(expectedOutput, node);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
new file mode 100644
index 000000000..f31fe261d
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/TypeBindingTests308.java
@@ -0,0 +1,1627 @@
+/*******************************************************************************
+ * Copyright (c) 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.tests.dom;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+
+import junit.framework.Test;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ArrayCreation;
+import org.eclipse.jdt.core.dom.ArrayType;
+import org.eclipse.jdt.core.dom.Assignment;
+import org.eclipse.jdt.core.dom.Block;
+import org.eclipse.jdt.core.dom.CastExpression;
+import org.eclipse.jdt.core.dom.CatchClause;
+import org.eclipse.jdt.core.dom.ClassInstanceCreation;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.CreationReference;
+import org.eclipse.jdt.core.dom.EnhancedForStatement;
+import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.ExpressionStatement;
+import org.eclipse.jdt.core.dom.FieldDeclaration;
+import org.eclipse.jdt.core.dom.IAnnotationBinding;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.IfStatement;
+import org.eclipse.jdt.core.dom.InstanceofExpression;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.ParameterizedType;
+import org.eclipse.jdt.core.dom.ParenthesizedExpression;
+import org.eclipse.jdt.core.dom.PrefixExpression;
+import org.eclipse.jdt.core.dom.QualifiedType;
+import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.core.dom.TryStatement;
+import org.eclipse.jdt.core.dom.Type;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.dom.TypeMethodReference;
+import org.eclipse.jdt.core.dom.TypeParameter;
+import org.eclipse.jdt.core.dom.UnionType;
+import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
+import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
+import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
+import org.eclipse.jdt.core.dom.WildcardType;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+
+public class TypeBindingTests308 extends ConverterTestSetup {
+
+ ICompilationUnit workingCopy;
+
+ public static Test suite() {
+ return buildModelTestSuite(TypeBindingTests308.class);
+ }
+ public void setUpSuite() throws Exception {
+ super.setUpSuite();
+ this.ast = AST.newAST(AST.JLS8);
+ }
+ public TypeBindingTests308(String testName){
+ super(testName);
+ }
+ static {
+// TESTS_NUMBERS = new int[] { };
+// TESTS_RANGE = new int[] { };
+// TESTS_NAMES = new String[] {"test027"};
+ }
+
+ private void verifyAnnotationOnType(Type type, String[] annots) {
+ verifyAnnotationsOnBinding(type.resolveBinding(), annots);
+ }
+
+ private void verifyAnnotationsOnBinding(ITypeBinding binding, String[] annots) {
+ IAnnotationBinding[] annotations = binding.getTypeAnnotations();
+ assertNotNull("Should not be null", annotations);
+ int length = annots.length;
+ assertEquals("Incorrect type use annotations", length, annotations.length);
+ for (int i = 0; i < length; i++) {
+ assertEquals("Incorrect annotation", annots[i], (annotations[i] == null) ? null : annotations[i].toString());
+ }
+ }
+
+ public void test000() throws Exception {
+ String contents =
+ "public class X extends @Marker @SingleMember(0) @Normal(value = 0) Object {\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface SingleMember { int value() default 0;}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Normal { int value() default 0;}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 4, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ Type type = typeDecl.getSuperclassType();
+ assertNotNull("Super class should not be null", type);
+
+ verifyAnnotationOnType(type, new String[]{"@Marker()", "@SingleMember(value = 0)", "@Normal(value = 0)"});
+ }
+ public void test001() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " @Marker int x;\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 2, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ FieldDeclaration[] fields = typeDecl.getFields();
+ assertEquals("Incorrect field", 1, fields.length);
+ FieldDeclaration field = fields[0];
+ verifyAnnotationOnType(field.getType(), new String[]{"@Marker()"});
+ }
+ public void test002() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " @Marker <@Marker2 T> int x() { return 10; };\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_PARAMETER)\n" +
+ "@interface Marker2{}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 3, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect method", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ List params = method.typeParameters();
+ TypeParameter param = (TypeParameter) params.get(0);
+ ITypeBinding binding = param.resolveBinding();
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker2()"});
+ verifyAnnotationOnType(method.getReturnType2(), new String[]{"@Marker()"});
+ }
+ public void test003() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " int x(@Marker int p) { return 10; };\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 2, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect method", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ List params = method.parameters();
+ SingleVariableDeclaration param = (SingleVariableDeclaration) params.get(0);
+ ITypeBinding binding = param.resolveBinding().getType();
+
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker()"});
+ verifyAnnotationOnType(param.getType(), new String[]{"@Marker()"});
+ }
+ public void test004() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " int x(@Marker int ... p) { return 10; };\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 2, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect method", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ List params = method.parameters();
+ SingleVariableDeclaration param = (SingleVariableDeclaration) params.get(0);
+ verifyAnnotationOnType(param.getType(), new String[]{"@Marker()"});
+ }
+
+ public void test005() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " int x(@Marker int @Marker2 [] @Marker3 ... p) { return 10; };\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker3 {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 4, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect method", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ List params = method.parameters();
+ SingleVariableDeclaration param = (SingleVariableDeclaration) params.get(0);
+ ArrayType type = (ArrayType) param.getType();
+ ITypeBinding binding = type.resolveBinding();
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker2()"});
+ verifyAnnotationsOnBinding(param.resolveBinding().getType(), new String[]{"@Marker2()"});
+ binding = binding.getComponentType();
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker()"});
+ }
+ public void test006() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " int x() {\n" +
+ " try {\n" +
+ " } catch (@Marker NullPointerException | @Marker2 ArrayIndexOutOfBoundsException e) {\n" +
+ " }\n" +
+ " return 10;\n" +
+ " }\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 3, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect method", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ List statements = method.getBody().statements();
+ TryStatement trySt = (TryStatement) statements.get(0);
+ CatchClause catchCl = (CatchClause) trySt.catchClauses().get(0);
+ UnionType union = (UnionType) catchCl.getException().getType();
+ types = union.types();
+ assertEquals("Incorrect union types", 2, types.size());
+ Type type = (Type) types.get(0);
+ verifyAnnotationOnType(type, new String[]{"@Marker()"});
+
+ type = (Type) types.get(1);
+ verifyAnnotationOnType(type, new String[]{"@Marker2()"});
+ }
+ public void test007() throws Exception {
+ String contents =
+ "package java.lang;\n" +
+ "public class X {\n" +
+ " public void x() throws Exception {\n" +
+ " try (@Marker LocalStream p = null; final @Marker2 LocalStream q = null; @Marker3 final LocalStream r = null) {}\n" +
+ " }\n" +
+ "}\n" +
+ "class LocalStream implements AutoCloseable {\n" +
+ " public void close() throws Exception {}\n" +
+ "}\n" +
+ "interface AutoCloseable {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker3 {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/java/lang/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 6, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect method", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ List statements = method.getBody().statements();
+ TryStatement trySt = (TryStatement) statements.get(0);
+ List resources = trySt.resources();
+ assertEquals("Incorrect no of resources", 3, resources.size());
+ VariableDeclarationExpression resource = (VariableDeclarationExpression) resources.get(0);
+ Type type = resource.getType();
+ assertNotNull("Resource type should not be null", type);
+ verifyAnnotationOnType(type, new String[]{"@Marker()"});
+
+ resource = (VariableDeclarationExpression) resources.get(1);
+ type = resource.getType();
+ assertNotNull("Resource type should not be null", type);
+ verifyAnnotationOnType(type, new String[]{"@Marker2()"});
+
+ resource = (VariableDeclarationExpression) resources.get(2);
+ type = resource.getType();
+ assertNotNull("Resource type should not be null", type);
+ verifyAnnotationOnType(type, new String[]{"@Marker3()"});
+ }
+ public void test008() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " int x() {\n" +
+ " for (@Marker int i: new int[3]) {}\n" +
+ " for (final @Marker int i: new int[3]) {}\n" +
+ " for (@Marker final int i: new int[3]) {}\n" +
+ " return 10;\n" +
+ " }\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 2, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect method", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ List statements = method.getBody().statements();
+ EnhancedForStatement forStmt = (EnhancedForStatement) statements.get(0);
+ SingleVariableDeclaration param = forStmt.getParameter();
+ Type type = param.getType();
+ assertNotNull("Resource type should not be null", type);
+ ITypeBinding binding = param.resolveBinding().getType();
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker()"});
+ binding = type.resolveBinding();
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker()"});
+ }
+ public void test009() throws Exception {
+ String contents =
+ "interface I {\n" +
+ " Object copy(int [] ia);\n" +
+ "}\n" +
+ "public class X {\n" +
+ " public static void main(String [] args) {\n" +
+ " I i = @Marker int @Marker2 []::clone;\n" +
+ " }\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 4, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(1);
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect method", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ List statements = method.getBody().statements();
+ VariableDeclarationStatement stmt = (VariableDeclarationStatement) statements.get(0);
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) stmt.fragments().get(0);
+ TypeMethodReference lambda = (TypeMethodReference) fragment.getInitializer();
+ ArrayType type = (ArrayType) lambda.getType();
+
+ verifyAnnotationOnType(type, new String[]{"@Marker2()"});
+ ITypeBinding binding = type.resolveBinding();
+ binding = binding.getComponentType();
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker()"});
+ }
+ public void test010() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " public static void main(String [] args) {\n" +
+ " int i [] = new @Marker int @Marker2 [4];\n" +
+ " int j [] = new @Marker2 int @Marker [] { 10 };\n" +
+ " }\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 3, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect method", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ List statements = method.getBody().statements();
+ VariableDeclarationStatement stmt = (VariableDeclarationStatement) statements.get(0);
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) stmt.fragments().get(0);
+ ArrayCreation arrayCr = (ArrayCreation) fragment.getInitializer();
+
+ ArrayType type = arrayCr.getType();
+ ITypeBinding binding = type.resolveBinding();
+ verifyAnnotationOnType(type, new String[]{"@Marker2()"});
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker2()"});
+ binding = binding.getComponentType();
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker()"});
+
+ stmt = (VariableDeclarationStatement) statements.get(1);
+ fragment = (VariableDeclarationFragment) stmt.fragments().get(0);
+ arrayCr = (ArrayCreation) fragment.getInitializer();
+ type = arrayCr.getType();
+
+ binding = type.resolveBinding();
+ verifyAnnotationOnType(type, new String[]{"@Marker()"});
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker()"});
+ binding = binding.getComponentType();
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker2()"});
+ }
+ public void test011() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " public static void main(String [] args) {\n" +
+ " int i = (@Marker int) 0;\n" +
+ " int j [] = (@Marker int @Marker2 []) null;\n" +
+ " }\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 3, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect method", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ List statements = method.getBody().statements();
+ VariableDeclarationStatement stmt = (VariableDeclarationStatement) statements.get(0);
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) stmt.fragments().get(0);
+ CastExpression castExp = (CastExpression) fragment.getInitializer();
+ Type type = castExp.getType();
+ verifyAnnotationOnType(type, new String[]{"@Marker()"});
+
+ stmt = (VariableDeclarationStatement) statements.get(1);
+ fragment = (VariableDeclarationFragment) stmt.fragments().get(0);
+ castExp = (CastExpression) fragment.getInitializer();
+ ArrayType arrayType = (ArrayType) castExp.getType();
+
+ ITypeBinding binding = arrayType.resolveBinding();
+ verifyAnnotationOnType(arrayType, new String[]{"@Marker2()"});
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker2()"});
+ binding = binding.getComponentType();
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker()"});
+ }
+ public void test012() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " public static void main(String args) {\n" +
+ " if (args instanceof @Marker String) {\n" +
+ " }\n" +
+ " }\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 2, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect method", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ List statements = method.getBody().statements();
+ IfStatement ifStmt = (IfStatement) statements.get(0);
+ InstanceofExpression instanceOf = (InstanceofExpression) ifStmt.getExpression();
+ Type type = instanceOf.getRightOperand();
+ verifyAnnotationOnType(type, new String[]{"@Marker()"});
+ }
+ public void test013() throws Exception {
+ String contents =
+ "public class X extends Y<@Marker(10) Integer, String> {}\n" +
+ "class Y<T, V> {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {int value();}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 3, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ ParameterizedType superClass = (ParameterizedType) typeDecl.getSuperclassType();
+ List arguments = superClass.typeArguments();
+ assertEquals("Incorrect no of type arguments", 2, arguments.size());
+ Type type = (Type) arguments.get(0);
+
+ verifyAnnotationOnType(type, new String[]{"@Marker(value = 10)"});
+ }
+ public void test014() throws Exception {
+ String contents =
+ "public class X<T extends Object & Comparable<? super @Marker String>> {}\n" +
+ "class Y<T> {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 3, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ List typeParams = typeDecl.typeParameters();
+
+ TypeParameter typeParam = (TypeParameter) typeParams.get(0);
+ List bounds = typeParam.typeBounds();
+ assertEquals("Incorrect no of type bounds", 2, bounds.size());
+ ParameterizedType type = (ParameterizedType) bounds.get(1);
+ typeParams = type.typeArguments();
+ assertEquals("Incorrect type params", 1, typeParams.size());
+ WildcardType wildcard = (WildcardType)typeParams.get(0);
+ Type bound = wildcard.getBound();
+ assertNotNull("Bound should not be null", bound);
+ verifyAnnotationOnType(bound, new String[]{"@Marker()"});
+ }
+ public void test015() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " void foo(Map<@Marker ? super @Marker2 Object, @Marker3 ? extends @Marker4 String> m){}\n" +
+ " void goo(Map<@Marker4 ? extends @Marker3 Object, @Marker2 ? super @Marker String> m){}\n" +
+ "}\n" +
+ "class Map<K, V>{}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker3 {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker4 {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true/*resolve*/);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 6, types.size());
+
+ MethodDeclaration[] methods = ((TypeDeclaration) types.get(0)).getMethods();
+ assertEquals("Incorrect no of metods", 2, methods.length);
+ MethodDeclaration method = methods[0];
+ SingleVariableDeclaration arg = (SingleVariableDeclaration) method.parameters().get(0);
+
+
+ List typeArgs = ((ParameterizedType) arg.getType()).typeArguments();
+
+ WildcardType wildcard = (WildcardType) typeArgs.get(0);
+ verifyAnnotationOnType(wildcard, new String[]{"@Marker()"});
+ Type type = wildcard.getBound();
+ verifyAnnotationOnType(type, new String[]{"@Marker2()"});
+
+ wildcard = (WildcardType) typeArgs.get(1);
+ verifyAnnotationOnType(wildcard, new String[]{"@Marker3()"});
+ type = wildcard.getBound();
+ verifyAnnotationOnType(type, new String[]{"@Marker4()"});
+
+ method = methods[1];
+ arg = (SingleVariableDeclaration) method.parameters().get(0);
+ typeArgs = ((ParameterizedType) arg.getType()).typeArguments();
+
+ wildcard = (WildcardType) typeArgs.get(0);
+ verifyAnnotationOnType(wildcard, new String[]{"@Marker4()"});
+ type = wildcard.getBound();
+ verifyAnnotationOnType(type, new String[]{"@Marker3()"});
+
+ wildcard = (WildcardType) typeArgs.get(1);
+ verifyAnnotationOnType(wildcard, new String[]{"@Marker2()"});
+ type = wildcard.getBound();
+ verifyAnnotationOnType(type, new String[]{"@Marker()"});
+ }
+ public void test016() throws Exception {
+ String contents =
+ "public class X<E> {\n" +
+ " class Y {\n" +
+ " E e;\n" +
+ " E getOtherElement(Object other) {\n" +
+ " if (!(other instanceof @Marker X<?>.Y)) {};\n" +
+ " return null;\n" +
+ " }\n" +
+ " }\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 2, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ typeDecl = typeDecl.getTypes()[0];
+ MethodDeclaration method = typeDecl.getMethods()[0];
+ IfStatement ifStmt = (IfStatement) method.getBody().statements().get(0);
+ PrefixExpression prefix = (PrefixExpression ) ifStmt.getExpression();
+ ParenthesizedExpression operand = (ParenthesizedExpression) prefix.getOperand();
+ InstanceofExpression expression = (InstanceofExpression) operand.getExpression();
+ QualifiedType type = (QualifiedType) expression.getRightOperand();
+ verifyAnnotationOnType(type, new String[]{});
+ verifyAnnotationOnType(type.getQualifier(), new String[]{"@Marker()"});
+ }
+ public void test017() throws Exception {
+ String contents =
+ "public class X<P, C> {\n" +
+ " public X() {\n" +
+ " if (!(this instanceof @Marker X)) {}\n" +
+ " }\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 2, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration method = typeDecl.getMethods()[0];
+ IfStatement ifStmt = (IfStatement) method.getBody().statements().get(0);
+ PrefixExpression prefix = (PrefixExpression ) ifStmt.getExpression();
+ ParenthesizedExpression operand = (ParenthesizedExpression) prefix.getOperand();
+ InstanceofExpression expression = (InstanceofExpression) operand.getExpression();
+ verifyAnnotationOnType(expression.getRightOperand(), new String[]{"@Marker()"});
+ }
+ public void test018() throws Exception {
+ String contents =
+ "interface I {\n" +
+ " void foo(Y<String>.Z z, int x);\n" +
+ "}\n" +
+ "public class X {\n" +
+ " public static void main(String [] args) {\n" +
+ " I i = Y<String>.@Marker Z::foo;\n" +
+ " i.foo(new Y<String>().new Z(), 10); \n" +
+ " }\n" +
+ "}\n" +
+ "class Y<T> {\n" +
+ " class Z {\n" +
+ " void foo(int x) {\n" +
+ " }\n" +
+ " }\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 4, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(1);
+ MethodDeclaration method = typeDecl.getMethods()[0];
+ VariableDeclarationStatement statement = (VariableDeclarationStatement) method.getBody().statements().get(0);
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) statement.fragments().get(0);
+ TypeMethodReference initializer = (TypeMethodReference) fragment.getInitializer();
+ Type type = initializer.getType();
+ verifyAnnotationOnType(type, new String[]{"@Marker()"});
+ assertEquals("Should be a qualified type", ASTNode.QUALIFIED_TYPE, type.getNodeType());
+ verifyAnnotationOnType(((QualifiedType) type).getQualifier() , new String[]{});
+ }
+ public void test019() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " public static void main(String [] args) {\n" +
+ " X [] x = new @Marker X @Marker2 [5];\n" +
+ " X [] x2 = new @Marker2 X @Marker [] { null };\n" +
+ " }\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 3, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration method = typeDecl.getMethods()[0];
+ List statements = method.getBody().statements();
+ assertEquals("Incorrect no of statements", 2, statements.size());
+ VariableDeclarationStatement statement = (VariableDeclarationStatement) statements.get(0);
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) statement.fragments().get(0);
+ ArrayCreation initializer = (ArrayCreation) fragment.getInitializer();
+ ArrayType arrayType = initializer.getType();
+ ITypeBinding binding = arrayType.resolveBinding();
+
+ verifyAnnotationOnType(arrayType, new String[]{"@Marker2()"});
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker2()"});
+
+ binding = binding.getComponentType();
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker()"});
+
+ statement = (VariableDeclarationStatement) statements.get(1);
+ fragment = (VariableDeclarationFragment) statement.fragments().get(0);
+ initializer = (ArrayCreation) fragment.getInitializer();
+ arrayType = initializer.getType();
+ binding = arrayType.resolveBinding();
+ verifyAnnotationOnType(arrayType, new String[]{"@Marker()"});
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker()"});
+
+ binding = binding.getComponentType();
+ verifyAnnotationsOnBinding(binding, new String[]{"@Marker2()"});
+ }
+ public void test020() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " public static void main(String [] args) {\n" +
+ " Map.Entry<String, String> [] e = (Map.@Marker Entry<String, String> []) null;\n" +
+ " }\n" +
+ "}\n" +
+ "class Map<K, V> {\n" +
+ " interface Entry<K, V> {}\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 3, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration method = typeDecl.getMethods()[0];
+ List statements = method.getBody().statements();
+ assertEquals("Incorrect no of statements", 1, statements.size());
+ VariableDeclarationStatement statement = (VariableDeclarationStatement) statements.get(0);
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) statement.fragments().get(0);
+ CastExpression castExp = (CastExpression) fragment.getInitializer();
+ ArrayType arrayType = (ArrayType) castExp.getType();
+ verifyAnnotationOnType(arrayType, new String[]{});
+ ParameterizedType type = (ParameterizedType) arrayType.getElementType();
+ verifyAnnotationOnType(type.getType(), new String[]{"@Marker()"});
+ }
+ public void test021() throws Exception {
+ String contents =
+ "import java.io.Serializable;\n" +
+ "import java.util.List;\n" +
+ "public class X<T extends Comparable<T> & Serializable> {\n" +
+ " void foo(List<? extends @Marker @Marker2 Comparable<T>> p) {} \n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 3, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration method = typeDecl.getMethods()[0];
+ SingleVariableDeclaration param = (SingleVariableDeclaration) method.parameters().get(0);
+ Type type = param.getType();
+ assertEquals("Should be a parameterized type", ASTNode.PARAMETERIZED_TYPE, type.getNodeType());
+ List typeArgs = ((ParameterizedType) type).typeArguments();
+ assertEquals("Incorrect type args", 1, typeArgs.size());
+ WildcardType wildcard = (WildcardType) typeArgs.get(0);
+ ParameterizedType bound = (ParameterizedType) wildcard.getBound();
+ verifyAnnotationOnType(bound, new String[]{"@Marker()", "@Marker2()"});
+ }
+ public void test022() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " X x = new @Marker X();\n" +
+ " X y = new <String> @Marker X();\n" +
+ " <T> X(){}\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 2, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ FieldDeclaration[] fields = typeDecl.getFields();
+ assertEquals("Incorrect no of fields", 2, fields.length);
+ FieldDeclaration field = fields[0];
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ ClassInstanceCreation creation = (ClassInstanceCreation) fragment.getInitializer();
+ verifyAnnotationOnType(creation.getType(), new String[]{"@Marker()"});
+
+ field = fields[1];
+ fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ creation = (ClassInstanceCreation) fragment.getInitializer();
+ verifyAnnotationOnType(creation.getType(), new String[]{"@Marker()"});
+ }
+ public void test023() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " class Y {\n" +
+ " <T> Y(){}\n" +
+ " }\n" +
+ " Y y1 = new @Marker X().new @Marker2 Y();\n" +
+ " Y y2 = new @Marker2 X().new <String> @Marker Y();\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 3, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ FieldDeclaration[] fields = typeDecl.getFields();
+ assertEquals("Incorrect no of fields", 2, fields.length);
+ FieldDeclaration field = fields[0];
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ ClassInstanceCreation creation = (ClassInstanceCreation) fragment.getInitializer();
+ verifyAnnotationOnType(creation.getType(), new String[]{"@Marker2()"});
+ creation = (ClassInstanceCreation) creation.getExpression();
+ verifyAnnotationOnType(creation.getType(), new String[]{"@Marker()"});
+
+ field = fields[1];
+ fragment = (VariableDeclarationFragment) field.fragments().get(0);
+ creation = (ClassInstanceCreation) fragment.getInitializer();
+ verifyAnnotationOnType(creation.getType(), new String[]{"@Marker()"});
+ creation = (ClassInstanceCreation) creation.getExpression();
+ verifyAnnotationOnType(creation.getType(), new String[]{"@Marker2()"});
+ }
+ public void test024() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " void foo() throws @Marker NullPointerException, @Marker2 ArrayIndexOutOfBoundsException {}\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 3, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ MethodDeclaration method = typeDecl.getMethods()[0];
+ List thrownTypes = method.thrownExceptionTypes();
+ assertEquals("Incorrect no of thrown exceptions", 2, thrownTypes.size());
+ Type type = (Type) thrownTypes.get(0);
+ verifyAnnotationOnType(type, new String[]{"@Marker()"});
+ type = (Type) thrownTypes.get(1);
+ verifyAnnotationOnType(type, new String[]{"@Marker2()"});
+ }
+ public void test025() throws Exception {
+ String contents =
+ "interface I {}\n" +
+ "interface J {}\n" +
+ "interface K extends @Marker I, @Marker2 J {}\n" +
+ "interface L {}\n" +
+ "public class X implements @Marker2 K, @Marker L {\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 7, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(2);
+ List interfaces = typeDecl.superInterfaceTypes();
+ assertEquals("Incorrect no of super interfaces", 2, interfaces.size());
+ verifyAnnotationOnType((Type) interfaces.get(0), new String[]{"@Marker()"});
+ verifyAnnotationOnType((Type) interfaces.get(1), new String[]{"@Marker2()"});
+
+ typeDecl = (TypeDeclaration) types.get(4);
+ interfaces = typeDecl.superInterfaceTypes();
+ assertEquals("Incorrect no of super interfaces", 2, interfaces.size());
+ verifyAnnotationOnType((Type) interfaces.get(0), new String[]{"@Marker2()"});
+ verifyAnnotationOnType((Type) interfaces.get(1), new String[]{"@Marker()"});
+ }
+ public void test026() throws Exception {
+ String contents =
+ "interface I {\n" +
+ " void foo(int x);\n" +
+ "}\n" +
+ "public class X {\n" +
+ " public static void main(String [] args) {\n" +
+ " I i = A.Y.@Marker Z ::foo;\n" +
+ " i.foo(10); \n" +
+ " }\n" +
+ "}\n" +
+ "class A {\n" +
+ " static class Y {\n" +
+ " static class Z {\n" +
+ " public static void foo(int x) {\n" +
+ " System.out.println(x);\n" +
+ " }\n" +
+ " }\n" +
+ " }\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 4, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(1);
+ MethodDeclaration method = typeDecl.getMethods()[0];
+ List statements = method.getBody().statements();
+
+ VariableDeclarationStatement stmt = (VariableDeclarationStatement) statements.get(0);
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) stmt.fragments().get(0);
+ TypeMethodReference lambda = (TypeMethodReference) fragment.getInitializer();
+ Type type = lambda.getType();
+
+ verifyAnnotationOnType(type, new String[]{"@Marker()"});
+ verifyAnnotationOnType(((QualifiedType)type).getQualifier(), new String[]{});
+ }
+ public void test027() throws Exception {
+ String contents =
+ "interface I {\n" +
+ " Y foo(int x);\n" +
+ "}\n" +
+ "public class X {\n" +
+ " class Z extends Y {\n" +
+ " public Z(int x) {\n" +
+ " super(x);\n" +
+ " }\n" +
+ " }\n" +
+ " public static void main(String [] args) {\n" +
+ " I i = @Marker W<@Marker2 Integer>::<@Marker3 String> new;\n" +
+ " }\n" +
+ "}\n" +
+ "class W<T> extends Y {\n" +
+ " public <C> W(T x) {\n" +
+ " super(0);\n" +
+ " }\n" +
+ "}\n" +
+ "class Y {\n" +
+ " public Y(int x) {\n" +
+ " }\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker2 {}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker3 {}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 7, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(1);
+ MethodDeclaration method = typeDecl.getMethods()[0];
+ List statements = method.getBody().statements();
+ VariableDeclarationStatement statement = (VariableDeclarationStatement) statements.get(0);
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) statement.fragments().get(0);
+ CreationReference lambda = (CreationReference) fragment.getInitializer();
+ Type type = lambda.getType();
+ verifyAnnotationOnType(type, new String[]{"@Marker()"});
+ ParameterizedType paramType = (ParameterizedType) type;
+ verifyAnnotationOnType((Type) paramType.typeArguments().get(0), new String[]{"@Marker2()"});
+ List typeArgs = lambda.typeArguments();
+ verifyAnnotationOnType((Type) typeArgs.get(0), new String[]{"@Marker3()"});
+ }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=418096
+ public void test028() throws Exception {
+ String contents =
+ "public class X {\n" +
+ " @TypeUseAnnotation(\"a\") String @TypeUseAnnotation(\"a1\") [] @TypeUseAnnotation(\"a2\") [] _field2 @TypeUseAnnotation(\"a3\") [], _field3 @TypeUseAnnotation(\"a4\") [][] = null;\n" +
+ "}" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface TypeUseAnnotation {\n" +
+ " String value() default \"\";\n" +
+ "}\n";
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 2, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+ FieldDeclaration[] fields = typeDecl.getFields();
+ assertEquals("Incorrect no of fields", 1, fields.length);
+ FieldDeclaration field = fields[0];
+ List fragments = field.fragments();
+ assertEquals("Incorrect no of fragments", 2, fragments.size());
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0);
+ ITypeBinding binding = fragment.resolveBinding().getType();
+ verifyAnnotationsOnBinding(binding, new String[]{"@TypeUseAnnotation(value = a3)"});
+ verifyAnnotationsOnBinding(binding = binding.getComponentType(), new String[]{"@TypeUseAnnotation(value = a1)"});
+ verifyAnnotationsOnBinding(binding = binding.getComponentType(), new String[]{"@TypeUseAnnotation(value = a2)"});
+ verifyAnnotationsOnBinding(binding = binding.getComponentType(), new String[]{"@TypeUseAnnotation(value = a)"});
+ fragment = (VariableDeclarationFragment) fragments.get(1);
+ binding = fragment.resolveBinding().getType();
+ verifyAnnotationsOnBinding(binding, new String[]{"@TypeUseAnnotation(value = a4)"});
+ verifyAnnotationsOnBinding(binding = binding.getComponentType(), new String[]{});
+ verifyAnnotationsOnBinding(binding = binding.getComponentType(), new String[]{"@TypeUseAnnotation(value = a1)"});
+ verifyAnnotationsOnBinding(binding = binding.getComponentType(), new String[]{"@TypeUseAnnotation(value = a2)"});
+ verifyAnnotationsOnBinding(binding = binding.getComponentType(), new String[]{"@TypeUseAnnotation(value = a)"});
+ }
+
+ public void testAnnotatedBinaryType() throws CoreException, IOException {
+ String jarName = "TypeBindingTests308.jar";
+ String srcName = "TypeBindingTests308_src.zip";
+ IJavaProject javaProject = getJavaProject("Converter18");
+ try {
+ String[] pathAndContents = new String[] {
+ "Outer.java",
+ "public class Outer {\n" +
+ " class Middle {\n" +
+ " class Inner {\n" +
+ " }\n" +
+ " }\n" +
+ " public @Marker(\"Outer\") Outer.@Marker (\"Middle\") Middle.@Marker(\"Inner\") Inner omi;\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {\n" +
+ " String value() default \"GOK\";\n" +
+ "}\n"
+ };
+
+ HashMap libraryOptions = new HashMap(javaProject.getOptions(true));
+ libraryOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED);
+ addLibrary(javaProject, jarName, srcName, pathAndContents, JavaCore.VERSION_1_8, libraryOptions);
+
+ String contents =
+ "public class X {\n" +
+ " void foo(Outer o) {\n" +
+ " o.omi = null;\n" +
+ " }\n" +
+ "}";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 1, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect no of methods", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ Block body = method.getBody();
+ ExpressionStatement stmt = (ExpressionStatement) body.statements().get(0);
+ Assignment assignment = (Assignment) stmt.getExpression();
+ Expression left = assignment.getLeftHandSide();
+ ITypeBinding type = left.resolveTypeBinding();
+ assertEquals("Wrong type", "@Marker{ value = (String)\"Outer\"} Outer.@Marker{ value = (String)\"Middle\"} Middle.@Marker{ value = (String)\"Inner\"} Inner", type.toString());
+ } finally {
+ removeLibrary(javaProject, jarName, srcName);
+ }
+ }
+ public void testAnnotatedBinaryType2() throws CoreException, IOException {
+ String jarName = "TypeBindingTests308.jar";
+ String srcName = "TypeBindingTests308_src.zip";
+ IJavaProject javaProject = getJavaProject("Converter18");
+ try {
+ String[] pathAndContents = new String[] {
+ "Outer.java",
+ "public class Outer {\n" +
+ " class Middle {\n" +
+ " class Inner {\n" +
+ " }\n" +
+ " }\n" +
+ " public @Marker(\"Outer\") Outer.@Marker (\"Middle\") Middle.@Marker(\"Inner\") Inner @Marker(\"Prefix []\") [] omi @Marker(\"Extended []\") [];\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface Marker {\n" +
+ " String value() default \"GOK\";\n" +
+ "}\n"
+ };
+
+ HashMap libraryOptions = new HashMap(javaProject.getOptions(true));
+ libraryOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED);
+ addLibrary(javaProject, jarName, srcName, pathAndContents, JavaCore.VERSION_1_8, libraryOptions);
+
+ String contents =
+ "public class X {\n" +
+ " void foo(Outer o) {\n" +
+ " o.omi = null;\n" +
+ " }\n" +
+ "}";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 1, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect no of methods", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ Block body = method.getBody();
+ ExpressionStatement stmt = (ExpressionStatement) body.statements().get(0);
+ Assignment assignment = (Assignment) stmt.getExpression();
+ Expression left = assignment.getLeftHandSide();
+ ITypeBinding type = left.resolveTypeBinding();
+ assertEquals("Wrong type", "@Marker{ value = (String)\"Outer\"} Outer.@Marker{ value = (String)\"Middle\"} Middle.@Marker{ value = (String)\"Inner\"} Inner @Marker{ value = (String)\"Extended []\"} [] @Marker{ value = (String)\"Prefix []\"} []", type.toString());
+ } finally {
+ removeLibrary(javaProject, jarName, srcName);
+ }
+ }
+ public void testAnnotatedBinaryType3() throws CoreException, IOException {
+ String jarName = "TypeBindingTests308.jar";
+ String srcName = "TypeBindingTests308_src.zip";
+ final IJavaProject javaProject = getJavaProject("Converter18");
+ try {
+ String[] pathAndContents = new String[] {
+ "Outer.java",
+ "public class Outer<K> {\n" +
+ " class Inner<P> {\n" +
+ " }\n" +
+ " public @T(1) Outer<@T(2) String>.@T(3) Inner<@T(4) Integer> @T(5) [] omi @T(6) [];\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ " int value();\n" +
+ "}\n"
+ };
+
+ HashMap libraryOptions = new HashMap(javaProject.getOptions(true));
+ libraryOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED);
+ addLibrary(javaProject, jarName, srcName, pathAndContents, JavaCore.VERSION_1_8, libraryOptions);
+
+ String contents =
+ "public class X {\n" +
+ " void foo(Outer<String> o) {\n" +
+ " o.omi = null;\n" +
+ " }\n" +
+ "}";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 1, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect no of methods", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ Block body = method.getBody();
+ ExpressionStatement stmt = (ExpressionStatement) body.statements().get(0);
+ Assignment assignment = (Assignment) stmt.getExpression();
+ Expression left = assignment.getLeftHandSide();
+ ITypeBinding type = left.resolveTypeBinding();
+ assertEquals("Wrong type", "@T{ value = (int)1} Outer<@T{ value = (int)2} String>.@T{ value = (int)3} Inner<@T{ value = (int)4} Integer> @T{ value = (int)6} [] @T{ value = (int)5} []", type.toString());
+ } finally {
+ removeLibrary(javaProject, jarName, srcName);
+ }
+ }
+
+ public void testAnnotatedBinaryType4() throws CoreException, IOException {
+ String jarName = "TypeBindingTests308.jar";
+ String srcName = "TypeBindingTests308_src.zip";
+ final IJavaProject javaProject = getJavaProject("Converter18");
+ try {
+ String[] pathAndContents = new String[] {
+ "Outer.java",
+ "public class Outer<K> {\n" +
+ " class Inner<P> {\n" +
+ " }\n" +
+ " @T(1) K @T(2) [] f @T(3) [];\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ " int value();\n" +
+ "}\n"
+ };
+
+ HashMap libraryOptions = new HashMap(javaProject.getOptions(true));
+ libraryOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED);
+ addLibrary(javaProject, jarName, srcName, pathAndContents, JavaCore.VERSION_1_8, libraryOptions);
+
+ String contents =
+ "public class X {\n" +
+ " void foo(Outer<String> o) {\n" +
+ " o.f = null;\n" +
+ " }\n" +
+ "}";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 1, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect no of methods", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ Block body = method.getBody();
+ ExpressionStatement stmt = (ExpressionStatement) body.statements().get(0);
+ Assignment assignment = (Assignment) stmt.getExpression();
+ Expression left = assignment.getLeftHandSide();
+ ITypeBinding type = left.resolveTypeBinding();
+ assertEquals("Wrong type", "@T{ value = (int)1} String @T{ value = (int)3} [] @T{ value = (int)2} []", type.toString());
+ } finally {
+ removeLibrary(javaProject, jarName, srcName);
+ }
+ }
+ public void testAnnotatedBinaryType5() throws CoreException, IOException {
+ String jarName = "TypeBindingTests308.jar";
+ String srcName = "TypeBindingTests308_src.zip";
+ final IJavaProject javaProject = getJavaProject("Converter18");
+ try {
+ String[] pathAndContents = new String[] {
+ "Outer.java",
+ "public class Outer<K> {\n" +
+ " class Inner<P> {\n" +
+ " }\n" +
+ " @T(1) Outer<@T(2) ? extends @T(3) String>.@T(4) Inner<@T(5) ? super @T(6) Integer> @T(7) [] f @T(8) [];\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ " int value();\n" +
+ "}\n"
+ };
+
+ HashMap libraryOptions = new HashMap(javaProject.getOptions(true));
+ libraryOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED);
+ addLibrary(javaProject, jarName, srcName, pathAndContents, JavaCore.VERSION_1_8, libraryOptions);
+
+ String contents =
+ "public class X {\n" +
+ " void foo(Outer<String> o) {\n" +
+ " o.f = null;\n" +
+ " }\n" +
+ "}";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 1, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect no of methods", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ Block body = method.getBody();
+ ExpressionStatement stmt = (ExpressionStatement) body.statements().get(0);
+ Assignment assignment = (Assignment) stmt.getExpression();
+ Expression left = assignment.getLeftHandSide();
+ ITypeBinding type = left.resolveTypeBinding();
+ assertEquals("Wrong type", "@T{ value = (int)1} Outer<@T{ value = (int)2} ? extends @T{ value = (int)3} String>.@T{ value = (int)4} Inner<@T{ value = (int)5} ? super @T{ value = (int)6} Integer> @T{ value = (int)8} [] @T{ value = (int)7} []", type.toString());
+ } finally {
+ removeLibrary(javaProject, jarName, srcName);
+ }
+ }
+ public void testAnnotatedBinaryType6() throws CoreException, IOException {
+ String jarName = "TypeBindingTests308.jar";
+ String srcName = "TypeBindingTests308_src.zip";
+ final IJavaProject javaProject = getJavaProject("Converter18");
+ try {
+ String[] pathAndContents = new String[] {
+ "Outer.java",
+ "public class Outer<K> {\n" +
+ " class Inner<P> {\n" +
+ " }\n" +
+ " @T(1) Outer.@T(2) Inner @T(3) [] f @T(4) [];\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ " int value();\n" +
+ "}\n"
+ };
+
+ HashMap libraryOptions = new HashMap(javaProject.getOptions(true));
+ libraryOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED);
+ addLibrary(javaProject, jarName, srcName, pathAndContents, JavaCore.VERSION_1_8, libraryOptions);
+
+ String contents =
+ "public class X {\n" +
+ " void foo(Outer<String> o) {\n" +
+ " o.f = null;\n" +
+ " }\n" +
+ "}";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 1, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect no of methods", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ Block body = method.getBody();
+ ExpressionStatement stmt = (ExpressionStatement) body.statements().get(0);
+ Assignment assignment = (Assignment) stmt.getExpression();
+ Expression left = assignment.getLeftHandSide();
+ ITypeBinding type = left.resolveTypeBinding();
+ assertEquals("Wrong type", "@T{ value = (int)1} Outer#RAW.@T{ value = (int)2} Inner#RAW @T{ value = (int)4} [] @T{ value = (int)3} []", type.toString());
+ } finally {
+ removeLibrary(javaProject, jarName, srcName);
+ }
+ }
+ public void testIntersectionCastType() throws CoreException, IOException {
+ String contents =
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface T1 {\n" +
+ "}\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface T2 {\n" +
+ "}\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface T3 {\n" +
+ "}\n" +
+ "public class X {\n" +
+ " Object o = (@T1 Object & @T2 Runnable & java.io.@T3 Serializable) null;\n" +
+ " Object p = (@T1 Object & @T2 Runnable & java.io.@T3 Serializable) null;\n" +
+ "}\n";
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 4, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(3);
+ FieldDeclaration[] fields = typeDecl.getFields();
+ assertEquals("Incorrect no of fields", 2, fields.length);
+ FieldDeclaration field = fields[0];
+ List fragments = field.fragments();
+ assertEquals("Incorrect no of fragments", 1, fragments.size());
+ VariableDeclarationFragment fragment = (VariableDeclarationFragment) fragments.get(0);
+ CastExpression cast = (CastExpression) fragment.getInitializer();
+ Type castType = cast.getType();
+ ITypeBinding binding1 = castType.resolveBinding();
+ assertEquals("Wrong annotations", "@T1 Object & @T2 Runnable & @T3 Serializable", binding1.toString());
+
+ field = fields[1];
+ fragments = field.fragments();
+ assertEquals("Incorrect no of fragments", 1, fragments.size());
+ fragment = (VariableDeclarationFragment) fragments.get(0);
+ cast = (CastExpression) fragment.getInitializer();
+ castType = cast.getType();
+ ITypeBinding binding2 = castType.resolveBinding();
+ assertEquals("Wrong annotations", "@T1 Object & @T2 Runnable & @T3 Serializable", binding2.toString());
+ assertSame("Should be equal", binding1, binding2);
+ }
+ public void testMemberType() throws CoreException, IOException {
+ String jarName = "TypeBindingTests308.jar";
+ String srcName = "TypeBindingTests308_src.zip";
+ final IJavaProject javaProject = getJavaProject("Converter18");
+ try {
+ String[] pathAndContents = new String[] {
+ "Outer.java",
+ "public class Outer {\n" +
+ " class Inner {\n" +
+ " }\n" +
+ "}\n"
+ };
+
+ HashMap libraryOptions = new HashMap(javaProject.getOptions(true));
+ libraryOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED);
+ addLibrary(javaProject, jarName, srcName, pathAndContents, JavaCore.VERSION_1_8, libraryOptions);
+
+ String contents =
+ "public class X {\n" +
+ " void foo(@T Outer o) {\n" +
+ " }\n" +
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ "}\n";
+
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 2, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect no of methods", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ List parameters = method.parameters();
+ SingleVariableDeclaration parameter = (SingleVariableDeclaration) parameters.get(0);
+ ITypeBinding binding = parameter.resolveBinding().getType();
+ assertEquals("@T Outer", binding.toString());
+ ITypeBinding [] memberTypes = binding.getDeclaredTypes();
+ assertEquals("Incorrect no of types", 1, memberTypes.length);
+ assertEquals("Incorrect no of types", "@T Outer.Inner", memberTypes[0].toString());
+ assertEquals("Incorrect no of types", "@T Outer", memberTypes[0].getEnclosingType().toString());
+ } finally {
+ removeLibrary(javaProject, jarName, srcName);
+ }
+ }
+ public void testMemberType2() throws CoreException, IOException {
+ String jarName = "TypeBindingTests308.jar";
+ String srcName = "TypeBindingTests308_src.zip";
+ final IJavaProject javaProject = getJavaProject("Converter18");
+ try {
+ String[] pathAndContents = new String[] {
+ "Outer.java",
+ "public class Outer {\n" +
+ " @T Outer f;\n"+
+ "}\n" +
+ "@java.lang.annotation.Target (java.lang.annotation.ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ "}\n"
+ };
+
+ HashMap libraryOptions = new HashMap(javaProject.getOptions(true));
+ libraryOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED);
+ addLibrary(javaProject, jarName, srcName, pathAndContents, JavaCore.VERSION_1_8, libraryOptions);
+
+ String contents =
+ "public class X {\n" +
+ " void foo(Outer o) {\n" +
+ " o.f = null;\n" +
+ " }\n" +
+ "}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 1, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect no of methods", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ Block body = method.getBody();
+ ExpressionStatement stmt = (ExpressionStatement) body.statements().get(0);
+ Assignment assignment = (Assignment) stmt.getExpression();
+ Expression left = assignment.getLeftHandSide();
+ ITypeBinding type = left.resolveTypeBinding();
+ assertEquals("Wrong type", "@T Outer", type.toString());
+ IVariableBinding[] declaredFields = type.getDeclaredFields();
+ assertEquals("Wrong type", 1, declaredFields.length);
+ assertEquals("Wrong type", "@T Outer", declaredFields[0].getType().toString());
+ } finally {
+ removeLibrary(javaProject, jarName, srcName);
+ }
+ }
+ public void testBinarySuperInterfaces() throws CoreException, IOException {
+ String jarName = "TypeBindingTests308.jar";
+ String srcName = "TypeBindingTests308_src.zip";
+ final IJavaProject javaProject = getJavaProject("Converter18");
+ try {
+ String[] pathAndContents = new String[] {
+ "Y.java",
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface T1 {\n" +
+ "}\n" +
+ "public abstract class Y implements Comparable<@T1 Y>{ \n" +
+ "}\n"
+ };
+
+ HashMap libraryOptions = new HashMap(javaProject.getOptions(true));
+ libraryOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED);
+ addLibrary(javaProject, jarName, srcName, pathAndContents, JavaCore.VERSION_1_8, libraryOptions);
+
+ String contents =
+ "public class X {\n" +
+ " void foo(Y y) {\n" +
+ " }\n" +
+ "}\n";
+
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 1, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(0);
+
+ MethodDeclaration[] methods = typeDecl.getMethods();
+ assertEquals("Incorrect no of methods", 1, methods.length);
+ MethodDeclaration method = methods[0];
+ List parameters = method.parameters();
+ SingleVariableDeclaration parameter = (SingleVariableDeclaration) parameters.get(0);
+ ITypeBinding binding = parameter.resolveBinding().getType();
+ ITypeBinding binding2 = binding.getInterfaces()[0].getTypeArguments()[0];
+ assertEquals("Wrong type", "@T1 Y", binding2.toString());
+ assertEquals("Wrong type", "Comparable<@T1 Y>", binding2.getInterfaces()[0].toString());
+ } finally {
+ removeLibrary(javaProject, jarName, srcName);
+ }
+ }
+ public void testMemberTypeSource() throws CoreException, IOException {
+ String contents =
+ "import java.lang.annotation.ElementType;\n" +
+ "import java.lang.annotation.Target;\n" +
+ "@Target(ElementType.TYPE_USE)\n" +
+ "@interface T {\n" +
+ "}\n" +
+ "public class X {\n" +
+ " class Y {}\n" +
+ " @T X.Y xy;\n" +
+ "}\n";
+ this.workingCopy = getWorkingCopy("/Converter18/src/X.java", true);
+ ASTNode node = buildAST(contents, this.workingCopy);
+ assertEquals("Not a compilation unit", ASTNode.COMPILATION_UNIT, node.getNodeType());
+ CompilationUnit compilationUnit = (CompilationUnit) node;
+ assertProblemsSize(compilationUnit, 0);
+ List types = compilationUnit.types();
+ assertEquals("Incorrect no of types", 2, types.size());
+ TypeDeclaration typeDecl = (TypeDeclaration) types.get(1);
+ FieldDeclaration[] fields = typeDecl.getFields();
+ assertEquals("Incorrect no of fields", 1, fields.length);
+ FieldDeclaration field = fields[0];
+ ITypeBinding binding = field.getType().resolveBinding();
+ assertEquals("Wrong Type", "@T X", (binding = binding.getEnclosingType()).toString());
+ assertEquals("Wrong Type", "@T X.Y", (binding = binding.getDeclaredTypes()[0]).toString());
+ }
+}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
index 6d10741a9..603f64167 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java
@@ -401,7 +401,7 @@ public abstract class AbstractJavaModelTests extends SuiteOfTestCases {
}
protected void addExternalLibrary(IJavaProject javaProject, String jarPath, String[] pathAndContents, String[] nonJavaResources, String compliance) throws Exception {
- String[] claspath = get15LibraryIfNeeded(compliance);
+ String[] claspath = getJCL15PlusLibraryIfNeeded(compliance);
org.eclipse.jdt.core.tests.util.Util.createJar(pathAndContents, nonJavaResources, jarPath, claspath, compliance);
addLibraryEntry(javaProject, new Path(jarPath), true/*exported*/);
}
@@ -460,7 +460,7 @@ public abstract class AbstractJavaModelTests extends SuiteOfTestCases {
IProject project = javaProject.getProject();
String projectLocation = project.getLocation().toOSString();
String jarPath = projectLocation + File.separator + jarName;
- String[] claspath = get15LibraryIfNeeded(compliance);
+ String[] claspath = getJCL15PlusLibraryIfNeeded(compliance);
org.eclipse.jdt.core.tests.util.Util.createJar(pathAndContents, nonJavaResources, jarPath, claspath, compliance, options);
if (pathAndContents != null && pathAndContents.length != 0) {
String sourceZipPath = projectLocation + File.separator + sourceZipName;
@@ -1835,8 +1835,13 @@ public abstract class AbstractJavaModelTests extends SuiteOfTestCases {
assertTrue("Did not find sibling", found);
}
}
- protected String[] get15LibraryIfNeeded(String compliance) throws JavaModelException, IOException {
- if (compliance.charAt(compliance.length()-1) >= '5' && (AbstractCompilerTest.getPossibleComplianceLevels() & AbstractCompilerTest.F_1_5) == 0) {
+ protected String[] getJCL15PlusLibraryIfNeeded(String compliance) throws JavaModelException, IOException {
+ if (compliance.charAt(compliance.length()-1) >= '8' && (AbstractCompilerTest.getPossibleComplianceLevels() & AbstractCompilerTest.F_1_8) != 0) {
+ // ensure that the JCL 18 lib is setup (i.e. that the jclMin18.jar is copied)
+ setUpJCLClasspathVariables("1.8");
+ return new String[] {getExternalJCLPathString("1.8")};
+ }
+ if (compliance.charAt(compliance.length()-1) >= '5' && (AbstractCompilerTest.getPossibleComplianceLevels() & AbstractCompilerTest.F_1_5) != 0) {
// ensure that the JCL 15 lib is setup (i.e. that the jclMin15.jar is copied)
setUpJCLClasspathVariables("1.5");
return new String[] {getExternalJCLPathString("1.5")};
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingExpressionsTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingExpressionsTest.java
index ff39a642e..144aebca2 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingExpressionsTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingExpressionsTest.java
@@ -263,23 +263,25 @@ public class ASTRewritingExpressionsTest extends ASTRewritingTest {
memberValuePair.setName(ast.newSimpleName("v"));
memberValuePair.setValue(ast.newNumberLiteral("99"));
annotationC.values().add(memberValuePair);
- arrayType.annotations().add(annotationC);
+ ExtraDimension dim0 = arrayType.getDimensionAt(0);
+ dim0.annotations().add(annotationC);
- arrayType= ast.newArrayType(arrayType);
SingleMemberAnnotation annotationB= ast.newSingleMemberAnnotation();
annotationB.setTypeName(ast.newSimpleName("B"));
annotationB.setValue(ast.newNumberLiteral("0"));
- arrayType.annotations().add(annotationB);
+ ExtraDimension dim1 = ast.newExtraDimension();
+ dim1.annotations().add(annotationB);
+ arrayType.dimensions().add(0, dim1);
- arrayType= ast.newArrayType(arrayType);
MarkerAnnotation annotationA= ast.newMarkerAnnotation();
annotationA.setTypeName(ast.newSimpleName("A"));
- arrayType.annotations().add(annotationA);
-
- arrayCreation.setType(arrayType);
+ ExtraDimension dim2 = ast.newExtraDimension();
+ dim2.annotations().add(annotationA);
+ arrayType.dimensions().add(0, dim2);
arrayCreation.dimensions().add(ast.newNumberLiteral("1"));
arrayCreation.dimensions().add(ast.newNumberLiteral("2"));
+ arrayCreation.setType(arrayType);
rewrite.getListRewrite(invocation, MethodInvocation.ARGUMENTS_PROPERTY).insertLast(arrayCreation, null);
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingMethodDeclTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingMethodDeclTest.java
index 7a2122503..55bd87404 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingMethodDeclTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingMethodDeclTest.java
@@ -111,7 +111,7 @@ public class ASTRewritingMethodDeclTest extends ASTRewritingTest {
listRewrite.remove(extraDimension, null);
}
for (int i= 0; i < extraDimensions; i++) {
- listRewrite.insertLast(methodDecl.getAST().newExtraDimension(), null);
+ listRewrite.insertFirst(methodDecl.getAST().newExtraDimension(), null);
}
}
}
@@ -993,7 +993,7 @@ public class ASTRewritingMethodDeclTest extends ASTRewritingTest {
List thrownExceptions= getThrownExceptions(methodDecl);
assertTrue("must be 0 thrown exceptions", thrownExceptions.size() == 0);
- Name newThrownException= ast.newSimpleName("InterruptedException");
+ ASTNode newThrownException= createNewExceptionType(ast, "InterruptedException");
rewrite.getListRewrite(methodDecl, getMethodThrownExceptionsProperty(ast)).insertFirst(newThrownException, null);
}
@@ -1015,7 +1015,7 @@ public class ASTRewritingMethodDeclTest extends ASTRewritingTest {
assertTrue("must be 1 thrown exceptions", thrownExceptions.size() == 1);
ASTNode firstException= (ASTNode) thrownExceptions.get(0);
- Name newThrownException= ast.newSimpleName("InterruptedException");
+ ASTNode newThrownException= createNewExceptionType(ast, "InterruptedException");
rewrite.getListRewrite(methodDecl, getMethodThrownExceptionsProperty(ast)).insertBefore(newThrownException, firstException, null);
}
{ // insert after last param & insert after first exception & add synchronized, static
@@ -1035,7 +1035,7 @@ public class ASTRewritingMethodDeclTest extends ASTRewritingTest {
assertTrue("must be 1 thrown exceptions", thrownExceptions.size() == 1);
ASTNode firstException= (ASTNode) thrownExceptions.get(0);
- Name newThrownException= ast.newSimpleName("InterruptedException");
+ ASTNode newThrownException= createNewExceptionType(ast, "InterruptedException");
rewrite.getListRewrite(methodDecl, getMethodThrownExceptionsProperty(ast)).insertAfter(newThrownException, firstException, null);
}
@@ -1057,7 +1057,7 @@ public class ASTRewritingMethodDeclTest extends ASTRewritingTest {
assertTrue("must be 2 thrown exceptions", thrownExceptions.size() == 2);
ASTNode firstException= (ASTNode) thrownExceptions.get(0);
- Name newThrownException= ast.newSimpleName("InterruptedException");
+ ASTNode newThrownException= createNewExceptionType(ast, "InterruptedException");
rewrite.getListRewrite(methodDecl, getMethodThrownExceptionsProperty(ast)).insertAfter(newThrownException, firstException, null);
}
{ // insert 2 params after first & replace the second exception and insert new after
@@ -1077,10 +1077,10 @@ public class ASTRewritingMethodDeclTest extends ASTRewritingTest {
List thrownExceptions= getThrownExceptions(methodDecl);
assertTrue("must be 2 thrown exceptions", thrownExceptions.size() == 2);
- Name newThrownException1= ast.newSimpleName("InterruptedException");
+ ASTNode newThrownException1= createNewExceptionType(ast, "InterruptedException");
rewrite.getListRewrite(methodDecl, getMethodThrownExceptionsProperty(ast)).insertLast(newThrownException1, null);
- Name newThrownException2= ast.newSimpleName("ArrayStoreException");
+ ASTNode newThrownException2= createNewExceptionType(ast, "ArrayStoreException");
rewrite.replace((ASTNode) thrownExceptions.get(1), newThrownException2, null);
}
{ // insert 2 params after last & remove the last exception and insert new after
@@ -1103,7 +1103,7 @@ public class ASTRewritingMethodDeclTest extends ASTRewritingTest {
ASTNode lastException= (ASTNode) thrownExceptions.get(2);
rewrite.remove(lastException, null);
- Name newThrownException= ast.newSimpleName("InterruptedException");
+ ASTNode newThrownException= createNewExceptionType(ast, "InterruptedException");
rewrite.getListRewrite(methodDecl, getMethodThrownExceptionsProperty(ast)).insertBefore(newThrownException, lastException, null);
}
{ // insert at first and last position & remove 2nd, add after 2nd, remove 3rd
@@ -1126,7 +1126,7 @@ public class ASTRewritingMethodDeclTest extends ASTRewritingTest {
rewrite.remove(secondException, null);
rewrite.remove(lastException, null);
- Name newThrownException= ast.newSimpleName("InterruptedException");
+ ASTNode newThrownException= createNewExceptionType(ast, "InterruptedException");
rewrite.getListRewrite(methodDecl, getMethodThrownExceptionsProperty(ast)).insertAfter(newThrownException, secondException, null);
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingReferenceExpressionTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingReferenceExpressionTest.java
index 75dd62cce..a6213b371 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingReferenceExpressionTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingReferenceExpressionTest.java
@@ -100,10 +100,9 @@ public class ASTRewritingReferenceExpressionTest extends ASTRewritingTest {
variableDeclarationStatement = (VariableDeclarationStatement) methodDecl.getBody().statements().get(1);
variableDeclarationFragment = (VariableDeclarationFragment) variableDeclarationStatement.fragments().get(0);
creationReference = (CreationReference) variableDeclarationFragment.getInitializer();
- typeParameter= ast.newTypeParameter();
- typeParameter.setName(ast.newSimpleName("Integer"));
+ SimpleType simpleType = ast.newSimpleType(ast.newSimpleName("Integer"));
listRewrite = rewrite.getListRewrite(creationReference, CreationReference.TYPE_ARGUMENTS_PROPERTY);
- listRewrite.insertLast(typeParameter, null);
+ listRewrite.insertLast(simpleType, null);
// case 3: delete a type argument.
variableDeclarationStatement = (VariableDeclarationStatement) methodDecl.getBody().statements().get(2);
@@ -129,15 +128,14 @@ public class ASTRewritingReferenceExpressionTest extends ASTRewritingTest {
variableDeclarationFragment = (VariableDeclarationFragment) variableDeclarationStatement.fragments().get(0);
creationReference = (CreationReference) variableDeclarationFragment.getInitializer();
listRewrite = rewrite.getListRewrite(creationReference, CreationReference.TYPE_ARGUMENTS_PROPERTY);
- typeParameter= ast.newTypeParameter();
- typeParameter.setName(ast.newSimpleName("String"));
- listRewrite.insertFirst(typeParameter, null);
+ simpleType = ast.newSimpleType(ast.newSimpleName("String"));
+ listRewrite.insertFirst(simpleType, null);
// case 8: change a CreationReference to a TypeMethodReference.
variableDeclarationStatement = (VariableDeclarationStatement) methodDecl.getBody().statements().get(7);
variableDeclarationFragment = (VariableDeclarationFragment) variableDeclarationStatement.fragments().get(0);
creationReference = (CreationReference) variableDeclarationFragment.getInitializer();
- SimpleType simpleType = ast.newSimpleType(ast.newQualifiedName(ast.newSimpleName("Y"), ast.newSimpleName("Z")));
+ simpleType = ast.newSimpleType(ast.newQualifiedName(ast.newSimpleName("Y"), ast.newSimpleName("Z")));
rewrite.replace(creationReference.getType(), simpleType, null);
}
@@ -270,10 +268,9 @@ public class ASTRewritingReferenceExpressionTest extends ASTRewritingTest {
VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) methodDecl.getBody().statements().get(2);
VariableDeclarationFragment variableDeclarationFragment = (VariableDeclarationFragment) variableDeclarationStatement.fragments().get(0);
ExpressionMethodReference expressionMethodReference = (ExpressionMethodReference) variableDeclarationFragment.getInitializer();
- TypeParameter typeParameter= ast.newTypeParameter();
- typeParameter.setName(ast.newSimpleName("String"));
+ SimpleType simpleType = ast.newSimpleType((ast.newSimpleName("String")));
rewrite.replace(expressionMethodReference.getExpression(), ast.newSimpleName("z"), null);
- rewrite.getListRewrite(expressionMethodReference, ExpressionMethodReference.TYPE_ARGUMENTS_PROPERTY).insertFirst(typeParameter, null);
+ rewrite.getListRewrite(expressionMethodReference, ExpressionMethodReference.TYPE_ARGUMENTS_PROPERTY).insertFirst(simpleType, null);
rewrite.replace(expressionMethodReference.getName(), ast.newSimpleName("bar"), null);
variableDeclarationStatement = (VariableDeclarationStatement) methodDecl.getBody().statements().get(3);
@@ -356,11 +353,10 @@ public class ASTRewritingReferenceExpressionTest extends ASTRewritingTest {
VariableDeclarationStatement variableDeclarationStatement = (VariableDeclarationStatement) methodDecl.getBody().statements().get(0);
VariableDeclarationFragment variableDeclarationFragment = (VariableDeclarationFragment) variableDeclarationStatement.fragments().get(0);
TypeMethodReference typeMethodReference = (TypeMethodReference) variableDeclarationFragment.getInitializer();
- TypeParameter typeParameter= ast.newTypeParameter();
- typeParameter.setName(ast.newSimpleName("Integer"));
+ SimpleType simpleType = ast.newSimpleType((ast.newSimpleName("Integer")));
Type newType = ast.newSimpleType(ast.newSimpleName("W"));
rewrite.replace(typeMethodReference.getType(), newType, null);
- rewrite.getListRewrite(typeMethodReference, TypeMethodReference.TYPE_ARGUMENTS_PROPERTY).insertFirst(typeParameter, null);
+ rewrite.getListRewrite(typeMethodReference, TypeMethodReference.TYPE_ARGUMENTS_PROPERTY).insertFirst(simpleType, null);
rewrite.replace(typeMethodReference.getName(), ast.newSimpleName("bar"), null);
variableDeclarationStatement = (VariableDeclarationStatement) methodDecl.getBody().statements().get(1);
@@ -450,9 +446,8 @@ public class ASTRewritingReferenceExpressionTest extends ASTRewritingTest {
variableDeclarationFragment = (VariableDeclarationFragment) variableDeclarationStatement.fragments().get(0);
superMethodReference = (SuperMethodReference) variableDeclarationFragment.getInitializer();
rewrite.remove(superMethodReference.getQualifier(), null);
- TypeParameter typeParameter= ast.newTypeParameter();
- typeParameter.setName(ast.newSimpleName("String"));
- rewrite.getListRewrite(superMethodReference, SuperMethodReference.TYPE_ARGUMENTS_PROPERTY).insertFirst(typeParameter, null);
+ SimpleType simpleType = ast.newSimpleType(ast.newSimpleName("String"));
+ rewrite.getListRewrite(superMethodReference, SuperMethodReference.TYPE_ARGUMENTS_PROPERTY).insertFirst(simpleType, null);
rewrite.replace(superMethodReference.getName(), ast.newSimpleName("foo"), null);
}
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingStatementsTest.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingStatementsTest.java
index 082fa57a5..eb8e53b4d 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingStatementsTest.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/rewrite/describing/ASTRewritingStatementsTest.java
@@ -75,7 +75,9 @@ import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.WhileStatement;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
+import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
+import org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter;
import org.eclipse.jface.text.Document;
import org.eclipse.text.edits.TextEdit;
@@ -5942,24 +5944,25 @@ public class ASTRewritingStatementsTest extends ASTRewritingTest {
ListRewrite listRewrite= rewrite.getListRewrite(fragment, VariableDeclarationFragment.EXTRA_DIMENSIONS2_PROPERTY);
ExtraDimension dim= ast.newExtraDimension();
MarkerAnnotation markerAnnotation;
- listRewrite.insertAt(dim, 0, null);
+ listRewrite.insertFirst(dim, null);
ArrayType creationType = creation.getType();
- ArrayType newArrayType = ast.newArrayType((ArrayType) ASTNode.copySubtree(ast, creationType));
- newArrayType = ast.newArrayType(newArrayType);
- rewrite.set(creation, ArrayCreation.TYPE_PROPERTY, newArrayType, null);
-
- listRewrite= rewrite.getListRewrite(newArrayType, ArrayType.ANNOTATIONS_PROPERTY);
+ ArrayType newArrayType = (ArrayType) ASTNode.copySubtree(ast, creationType);
+ newArrayType.dimensions().add(ast.newExtraDimension());
+
+ ExtraDimension dim0 = ast.newExtraDimension();
markerAnnotation= ast.newMarkerAnnotation();
markerAnnotation.setTypeName(ast.newSimpleName("Annot3"));
- listRewrite.insertAt(markerAnnotation, 0, null);
- newArrayType.annotations().add(markerAnnotation);
+ dim0.annotations().add(markerAnnotation);
markerAnnotation= ast.newMarkerAnnotation();
markerAnnotation.setTypeName(ast.newSimpleName("Annot2"));
- listRewrite.insertAt(markerAnnotation, 1, null);
+ dim0.annotations().add(markerAnnotation);
markerAnnotation= ast.newMarkerAnnotation();
markerAnnotation.setTypeName(ast.newSimpleName("Annot1"));
- listRewrite.insertAt(markerAnnotation, 2, null);
+ dim0.annotations().add(markerAnnotation);
+ newArrayType.dimensions().add(dim0);
+ rewrite.set(creation, ArrayCreation.TYPE_PROPERTY, newArrayType, null);
+
}
{
statement = (VariableDeclarationStatement) statements.get(1);
@@ -5978,43 +5981,44 @@ public class ASTRewritingStatementsTest extends ASTRewritingTest {
Expression exp = (Expression) expressions.get(1);
listRewrite.remove(exp, null);
- listRewrite = rewrite.getListRewrite(creationType, ArrayType.ANNOTATIONS_PROPERTY);
- MarkerAnnotation annotation = (MarkerAnnotation) creationType.annotations().get(0);
+ ExtraDimension dim = creationType.getDimensionAt(2);
+ listRewrite = rewrite.getListRewrite(dim, ExtraDimension.ANNOTATIONS_PROPERTY);
+ MarkerAnnotation annotation = (MarkerAnnotation) dim.annotations().get(0);
listRewrite.remove(annotation, null);
- creationType = (ArrayType) creationType.getComponentType();
- listRewrite = rewrite.getListRewrite(creationType, ArrayType.ANNOTATIONS_PROPERTY);
- annotation = (MarkerAnnotation) creationType.annotations().get(1);
+ dim = creationType.getDimensionAt(1);
+ listRewrite = rewrite.getListRewrite(dim, ExtraDimension.ANNOTATIONS_PROPERTY);
+ annotation = (MarkerAnnotation) dim.annotations().get(1);
listRewrite.remove(annotation, null);
- creationType = (ArrayType) creationType.getComponentType();
- listRewrite = rewrite.getListRewrite(creationType, ArrayType.ANNOTATIONS_PROPERTY);
- annotation = (MarkerAnnotation) creationType.annotations().get(1);
+ dim = creationType.getDimensionAt(0);
+ listRewrite = rewrite.getListRewrite(dim, ExtraDimension.ANNOTATIONS_PROPERTY);
+ annotation = (MarkerAnnotation) dim.annotations().get(1);
listRewrite.remove(annotation, null);
fragment = (VariableDeclarationFragment) fragments.get(1);
creation = (ArrayCreation) fragment.getInitializer();
creationType = creation.getType();
-
- listRewrite = rewrite.getListRewrite(creationType, ArrayType.ANNOTATIONS_PROPERTY);
- annotation = (MarkerAnnotation) creationType.annotations().get(0);
+ dim = creationType.getDimensionAt(2);
+ listRewrite = rewrite.getListRewrite(dim, ExtraDimension.ANNOTATIONS_PROPERTY);
+ annotation = (MarkerAnnotation) dim.annotations().get(1);
listRewrite.remove(annotation, null);
- annotation = (MarkerAnnotation) creationType.annotations().get(1);
+ annotation = (MarkerAnnotation) dim.annotations().get(0);
listRewrite.remove(annotation, null);
- creationType = (ArrayType) creationType.getComponentType();
- listRewrite = rewrite.getListRewrite(creationType, ArrayType.ANNOTATIONS_PROPERTY);
- annotation = (MarkerAnnotation) creationType.annotations().get(0);
+ dim = creationType.getDimensionAt(1);
+ listRewrite = rewrite.getListRewrite(dim, ExtraDimension.ANNOTATIONS_PROPERTY);
+ annotation = (MarkerAnnotation) dim.annotations().get(1);
listRewrite.remove(annotation, null);
- annotation = (MarkerAnnotation) creationType.annotations().get(1);
+ annotation = (MarkerAnnotation) dim.annotations().get(0);
listRewrite.remove(annotation, null);
- creationType = (ArrayType) creationType.getComponentType();
- listRewrite = rewrite.getListRewrite(creationType, ArrayType.ANNOTATIONS_PROPERTY);
- annotation = (MarkerAnnotation) creationType.annotations().get(0);
+ dim = creationType.getDimensionAt(0);
+ listRewrite = rewrite.getListRewrite(dim, ExtraDimension.ANNOTATIONS_PROPERTY);
+ annotation = (MarkerAnnotation) dim.annotations().get(1);
listRewrite.remove(annotation, null);
- annotation = (MarkerAnnotation) creationType.annotations().get(1);
+ annotation = (MarkerAnnotation) dim.annotations().get(0);
listRewrite.remove(annotation, null);
expressions = creation.dimensions();
@@ -6035,8 +6039,8 @@ public class ASTRewritingStatementsTest extends ASTRewritingTest {
buf.append("import java.lang.annotation.ElementType;\n");
buf.append("public class E {\n");
buf.append(" public void foo() {\n");
- buf.append(" int [] i [] @Annot1 @Annot2 [] @Annot1 @Annot3 [] = new int @Annot1 @Annot2 [2] @Annot2 @Annot3 [size()] @Annot2 @Annot1 [][] @Annot3 @Annot2 @Annot1[];\n");
- buf.append(" int [] j [][] = new int @Annot1 [2] @Annot2 [] @Annot3 [], k [][] = new int[2][10][size()];\n");
+ buf.append(" int [] i [] @Annot1 @Annot2 [] @Annot1 @Annot3 [] = new int @Annot1 @Annot2 [2] @Annot2 @Annot3 [size()] @Annot2 @Annot1 [][]@Annot3 @Annot2 @Annot1 [];\n");
+ buf.append(" int [] j [][] = new int @Annot2 [2] @Annot2 [] @Annot1 [], k [][] = new int [2] [10] [size()];\n");
buf.append(" }\n");
buf.append(" public int size() { return 2; }\n");
buf.append("}\n");
@@ -6086,10 +6090,10 @@ public class ASTRewritingStatementsTest extends ASTRewritingTest {
ArrayCreation creation = (ArrayCreation) fragment.getInitializer();
ArrayType arrayType = creation.getType();
- arrayType = (ArrayType) arrayType.getComponentType();
- ListRewrite listRewrite= rewrite.getListRewrite(arrayType, ArrayType.ANNOTATIONS_PROPERTY);
- listRewrite.remove((ASTNode)arrayType.annotations().get(0), null);
- listRewrite.remove((ASTNode)arrayType.annotations().get(1), null);
+ ExtraDimension dim = arrayType.getDimensionAt(1);
+ ListRewrite listRewrite= rewrite.getListRewrite(dim, ExtraDimension.ANNOTATIONS_PROPERTY);
+ listRewrite.remove((ASTNode)dim.annotations().get(0), null);
+ listRewrite.remove((ASTNode)dim.annotations().get(1), null);
rewrite.set(creation, ArrayCreation.TYPE_PROPERTY, arrayType, null);
}
{
@@ -6101,16 +6105,12 @@ public class ASTRewritingStatementsTest extends ASTRewritingTest {
assertEquals("Incorrect type", ASTNode.ARRAY_TYPE, type.getNodeType());
ArrayCreation creation = (ArrayCreation) fragment.getInitializer();
ArrayType creationType = creation.getType();
-
- ArrayType newArrayType = (ArrayType) creationType.getComponentType();
- rewrite.set(creation, ArrayCreation.TYPE_PROPERTY, newArrayType, null);
-
+ rewrite.remove(creationType.getDimensionAt(0), null);
fragment = (VariableDeclarationFragment) fragments.get(1);
creation = (ArrayCreation) fragment.getInitializer();
creationType = creation.getType();
- newArrayType = (ArrayType) creationType.getComponentType();
- rewrite.set(creation, ArrayCreation.TYPE_PROPERTY, newArrayType, null);
+ rewrite.remove(creationType.getDimensionAt(0), null);
}
// Get new code
String preview= evaluateRewrite(cu, rewrite);
@@ -6120,7 +6120,7 @@ public class ASTRewritingStatementsTest extends ASTRewritingTest {
buf.append("import java.lang.annotation.ElementType;\n");
buf.append("public class E {\n");
buf.append(" public void foo() {\n");
- buf.append(" int [] i [][] = new int @Annot1 @Annot2 [2][size(new int[][]{})];\n");
+ buf.append(" int [] i [][] = new int @Annot1 @Annot2 [2] [size(new int[][]{})] [];\n");
buf.append(" int [] j [][] = new int @Annot1 @Annot2 [2] @Annot2 @Annot3 [size(new int[]{})], k [][] = new int @Annot1 @Annot2 [2] @Annot2 @Annot3 [10];\n");
buf.append(" }\n");
buf.append(" public int size(Object obj) { return 2; }\n");
@@ -6133,6 +6133,29 @@ public class ASTRewritingStatementsTest extends ASTRewritingTest {
buf.append("@interface Annot3 {}\n");
assertEqualString(preview, buf.toString());
}
+
+ public void testBug413592a() throws Exception {
+ String buf = "default int func2(){return 1;}";
+ Document doc = new Document(buf);
+ String formattedString = "\tdefault int func2() {\n" +
+ "\t\treturn 1;\n" +
+ "\t}";
+ TextEdit edit = new ASTRewriteFormatter(null, null, JavaCore.getOptions(), "\n").formatString(CodeFormatter.K_CLASS_BODY_DECLARATIONS, buf, 0, buf.length(), 1);
+ edit.apply(doc);
+ assertTrue("Incorrect Formatting", doc.get().equals(formattedString));
+ }
+
+ public void testBug413592b() throws Exception {
+ String buf = "default int func2(){return 2*(3+4)/5/(6+7);}";
+ Document doc = new Document(buf);
+ String formattedString = "\tdefault int func2() {\n" +
+ "\t\treturn 2 * (3 + 4) / 5 / (6 + 7);\n" +
+ "\t}";
+ TextEdit edit = new ASTRewriteFormatter(null, null, JavaCore.getOptions(), "\n").formatString(CodeFormatter.K_CLASS_BODY_DECLARATIONS, buf, 0, buf.length(), 1);
+ edit.apply(doc);
+ assertTrue("Incorrect Formatting", doc.get().equals(formattedString));
+ }
+
}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
index 6861b53ed..3b2a95ec1 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnQualifiedTypeReference.java
@@ -56,13 +56,7 @@ public void aboutToResolve(Scope scope) {
/*
* No expansion of the completion reference into an array one
*/
-public TypeReference copyDims(int dim){
- return this;
-}
-/*
- * No expansion of the completion reference into an array one
- */
-public TypeReference copyDims(int dim, Annotation[][] annotationsOnDimensions){
+public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) {
return this;
}
protected TypeBinding getTypeBinding(Scope scope) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
index 0278e6602..4f4afa547 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnSingleTypeReference.java
@@ -59,13 +59,7 @@ public void aboutToResolve(Scope scope) {
/*
* No expansion of the completion reference into an array one
*/
-public TypeReference copyDims(int dim){
- return this;
-}
-/*
- * No expansion of the completion reference into an array one
- */
-public TypeReference copyDims(int dim, Annotation[][] annotationsOnDimensions){
+public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) {
return this;
}
protected TypeBinding getTypeBinding(Scope scope) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
index ab25be9e8..e8c854f28 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionParser.java
@@ -2993,18 +2993,13 @@ protected void consumeFormalParameter(boolean isVarArgs) {
int firstDimensions = this.intStack[this.intPtr--];
TypeReference type = getTypeReference(firstDimensions);
- final int typeDimensions = firstDimensions + extendedDimensions + (isVarArgs ? 1 : 0);
- if (typeDimensions != firstDimensions) {
- // jsr308 type annotations management
- Annotation [][] annotationsOnFirstDimensions = firstDimensions == 0 ? null : type.getAnnotationsOnDimensions();
- Annotation [][] annotationsOnAllDimensions = annotationsOnFirstDimensions;
- if (annotationsOnExtendedDimensions != null) {
- annotationsOnAllDimensions = getMergedAnnotationsOnDimensions(firstDimensions, annotationsOnFirstDimensions, extendedDimensions, annotationsOnExtendedDimensions);
+ if (isVarArgs || extendedDimensions != 0) {
+ if (isVarArgs) {
+ type = augmentTypeWithAdditionalDimensions(type, 1, varArgsAnnotations != null ? new Annotation[][] { varArgsAnnotations } : null, true);
}
- if (varArgsAnnotations != null) {
- annotationsOnAllDimensions = getMergedAnnotationsOnDimensions(firstDimensions + extendedDimensions, annotationsOnAllDimensions, 1, new Annotation[][]{varArgsAnnotations});
+ if (extendedDimensions != 0) { // combination illegal.
+ type = augmentTypeWithAdditionalDimensions(type, extendedDimensions, annotationsOnExtendedDimensions, false);
}
- type = copyDims(type, typeDimensions, annotationsOnAllDimensions);
type.sourceEnd = type.isParameterizedTypeReference() ? this.endStatementPosition : this.endPosition;
}
if (isVarArgs) {
@@ -3652,11 +3647,11 @@ protected void consumeMethodHeader() {
super.consumeMethodHeader();
pushOnElementStack(K_BLOCK_DELIMITER);
}
-protected void consumeMethodDeclaration(boolean isNotAbstract) {
+protected void consumeMethodDeclaration(boolean isNotAbstract, boolean isDefaultMethod) {
if (!isNotAbstract) {
popElement(K_BLOCK_DELIMITER);
}
- super.consumeMethodDeclaration(isNotAbstract);
+ super.consumeMethodDeclaration(isNotAbstract, isDefaultMethod);
}
protected void consumeModifiers() {
super.consumeModifiers();
@@ -4955,21 +4950,11 @@ protected StringLiteral createStringLiteral(char[] token, int start, int end, in
}
return super.createStringLiteral(token, start, end, lineNumber);
}
-protected TypeReference copyDims(TypeReference typeRef, int dim) {
+protected TypeReference augmentTypeWithAdditionalDimensions(TypeReference typeRef, int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) {
if (this.assistNode == typeRef) {
return typeRef;
}
- TypeReference result = super.copyDims(typeRef, dim);
- if (this.assistNodeParent == typeRef) {
- this.assistNodeParent = result;
- }
- return result;
-}
-protected TypeReference copyDims(TypeReference typeRef, int dim, Annotation[][] annotationsOnDimensions) {
- if (this.assistNode == typeRef) {
- return typeRef;
- }
- TypeReference result = super.copyDims(typeRef, dim, annotationsOnDimensions);
+ TypeReference result = super.augmentTypeWithAdditionalDimensions(typeRef, additionalDimensions, additionalAnnotations, isVarargs);
if (this.assistNodeParent == typeRef) {
this.assistNodeParent = result;
}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java
index 84cd86c61..bf268d206 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistParser.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 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
@@ -400,11 +400,11 @@ protected void consumeMethodBody() {
super.consumeMethodBody();
popElement(K_METHOD_DELIMITER);
}
-protected void consumeMethodDeclaration(boolean isNotAbstract) {
+protected void consumeMethodDeclaration(boolean isNotAbstract, boolean isDefaultMethod) {
if (!isNotAbstract) {
popElement(K_METHOD_DELIMITER);
}
- super.consumeMethodDeclaration(isNotAbstract);
+ super.consumeMethodDeclaration(isNotAbstract, isDefaultMethod);
}
protected void consumeMethodHeader() {
super.consumeMethodHeader();
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
index d4944f2c0..26ed61b91 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
@@ -669,18 +669,13 @@ protected void consumeFormalParameter(boolean isVarArgs) {
int firstDimensions = this.intStack[this.intPtr--];
TypeReference type = getTypeReference(firstDimensions);
- final int typeDimensions = firstDimensions + extendedDimensions + (isVarArgs ? 1 : 0);
- if (typeDimensions != firstDimensions) {
- // jsr308 type annotations management
- Annotation [][] annotationsOnFirstDimensions = firstDimensions == 0 ? null : type.getAnnotationsOnDimensions();
- Annotation [][] annotationsOnAllDimensions = annotationsOnFirstDimensions;
- if (annotationsOnExtendedDimensions != null) {
- annotationsOnAllDimensions = getMergedAnnotationsOnDimensions(firstDimensions, annotationsOnFirstDimensions, extendedDimensions, annotationsOnExtendedDimensions);
- }
- if (varArgsAnnotations != null) {
- annotationsOnAllDimensions = getMergedAnnotationsOnDimensions(firstDimensions + extendedDimensions, annotationsOnAllDimensions, 1, new Annotation[][]{varArgsAnnotations});
+ if (isVarArgs || extendedDimensions != 0) {
+ if (isVarArgs) {
+ type = augmentTypeWithAdditionalDimensions(type, 1, varArgsAnnotations != null ? new Annotation[][] { varArgsAnnotations } : null, true);
+ }
+ if (extendedDimensions != 0) { // combination illegal.
+ type = augmentTypeWithAdditionalDimensions(type, extendedDimensions, annotationsOnExtendedDimensions, false);
}
- type = copyDims(type, typeDimensions, annotationsOnAllDimensions);
type.sourceEnd = type.isParameterizedTypeReference() ? this.endStatementPosition : this.endPosition;
}
if (isVarArgs) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
index 8922355aa..4fa4be4e0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -181,14 +181,6 @@
* DuplicateInheritedDefaultMethods
* SuperAccessCannotBypassDirectSuper
* SuperCallCannotBypassOverride
- * IllegalModifierForInterfaceDefaultMethod
- * InheritedDefaultMethodConflictsWithOtherInherited
- * ConflictingNullAnnotations
- * ConflictingInheritedNullAnnotations
- * UnsafeElementTypeConversion
- * ArrayReferencePotentialNullReference
- * DereferencingNullableExpression
- * NullityMismatchingTypeAnnotation
* ConflictingNullAnnotations
* ConflictingInheritedNullAnnotations
* UnsafeElementTypeConversion
@@ -206,7 +198,18 @@
* TargetTypeNotAFunctionalInterface
* OuterLocalMustBeEffectivelyFinal
* IllegalModifiersForPackage
- *******************************************************************************/
+ * DuplicateAnnotationNotMarkedRepeatable
+ * DisallowedTargetForContainerAnnotation
+ * RepeatedAnnotationWithContainerAnnotation
+ * ContainingAnnotationMustHaveValue
+ * ContainingAnnotationHasNonDefaultMembers
+ * ContainingAnnotationHasWrongValueType
+ * ContainingAnnotationHasShorterRetention
+ * RepeatableAnnotationHasTargets
+ * RepeatableAnnotationTargetMismatch
+ * RepeatableAnnotationIsDocumented
+ * RepeatableAnnotationIsInherited
+*******************************************************************************/
package org.eclipse.jdt.core.compiler;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
@@ -1621,6 +1624,41 @@ void setSourceStart(int sourceStart);
int MultipleFunctionalInterfaces = TypeRelated + 895;
/** @since 3.9 BETA_JAVA8 */
int StaticInterfaceMethodNotBelow18 = Internal + Syntax + 896;
+ /** @since 3.9 BETA_JAVA8 */
+ int DuplicateAnnotationNotMarkedRepeatable = TypeRelated + 897;
+ /** @since 3.9 BETA_JAVA8 */
+ int DisallowedTargetForContainerAnnotation = TypeRelated + 898;
+ /** @since 3.9 BETA_JAVA8 */
+ int RepeatedAnnotationWithContainerAnnotation = TypeRelated + 899;
+
+ /**
+ * External problems -- These are problems defined by other plugins
+ */
+
+ /** @since 3.2 */
+ int ExternalProblemNotFixable = 900;
+
+ // indicates an externally defined problem that has a quick-assist processor
+ // associated with it
+ /** @since 3.2 */
+ int ExternalProblemFixable = 901;
+
+ /** @since 3.9 BETA_JAVA8 */
+ int ContainingAnnotationHasWrongValueType = TypeRelated + 902;
+ /** @since 3.9 BETA_JAVA8 */
+ int ContainingAnnotationMustHaveValue = TypeRelated + 903;
+ /** @since 3.9 BETA_JAVA8 */
+ int ContainingAnnotationHasNonDefaultMembers = TypeRelated + 904;
+ /** @since 3.9 BETA_JAVA8 */
+ int ContainingAnnotationHasShorterRetention = TypeRelated + 905;
+ /** @since 3.9 BETA_JAVA8 */
+ int RepeatableAnnotationHasTargets = TypeRelated + 906;
+ /** @since 3.9 BETA_JAVA8 */
+ int RepeatableAnnotationTargetMismatch = TypeRelated + 907;
+ /** @since 3.9 BETA_JAVA8 */
+ int RepeatableAnnotationIsDocumented = TypeRelated + 908;
+ /** @since 3.9 BETA_JAVA8 */
+ int RepeatableAnnotationIsInherited = TypeRelated + 909;
/**
* Errors/warnings from annotation based null analysis
@@ -1752,18 +1790,8 @@ void setSourceStart(int sourceStart);
int IllegalModifierCombinationForInterfaceMethod = MethodRelated + 1056;
/** @since 3.9 BETA_JAVA8 */
int IllegalStrictfpForAbstractInterfaceMethod = MethodRelated + 1057;
-
- /**
- * External problems -- These are problems defined by other plugins
- */
-
- /** @since 3.2 */
- int ExternalProblemNotFixable = 900;
-
- // indicates an externally defined problem that has a quick-assist processor
- // associated with it
- /** @since 3.2 */
- int ExternalProblemFixable = 901;
+ /** @since 3.9 BETA_JAVA8 */
+ int IllegalDefaultModifierSpecification = MethodRelated + 1058;
//{ObjectTeams:
int OTJ_RELATED = 1000000;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index c39682280..3e3919048 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -1507,7 +1507,7 @@ public class ClassFile implements TypeConstants, TypeIds {
for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) {
ExceptionLabel exceptionLabel = exceptionLabels[i];
if (exceptionLabel.exceptionTypeReference != null && (exceptionLabel.exceptionTypeReference.bits & ASTNode.HasTypeAnnotations) != 0) {
- exceptionLabel.exceptionTypeReference.getAllAnnotationContexts(AnnotationTargetTypeConstants.EXCEPTION_PARAMETER, i, allTypeAnnotationContexts);
+ exceptionLabel.exceptionTypeReference.getAllAnnotationContexts(AnnotationTargetTypeConstants.EXCEPTION_PARAMETER, i, allTypeAnnotationContexts, exceptionLabel.se7Annotations);
}
}
@@ -4610,10 +4610,7 @@ public class ClassFile implements TypeConstants, TypeIds {
int[] locations = Annotation.getLocations(
annotationContext.typeReference,
- annotationContext.primaryAnnotations,
- annotationContext.annotation,
- annotationContext.annotationsOnDimensions,
- annotationContext.dimensions);
+ annotationContext.annotation);
if (this.contentsOffset + 5 >= this.contents.length) {
resizeContents(5);
@@ -4631,10 +4628,7 @@ public class ClassFile implements TypeConstants, TypeIds {
int[] locations = Annotation.getLocations(
annotationContext.typeReference,
- null,
- annotationContext.annotation,
- null,
- 0);
+ annotationContext.annotation);
// reserve enough space
if (this.contentsOffset + 5 >= this.contents.length) {
resizeContents(5);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index 0b6622a36..875043ae5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -22,17 +22,23 @@
* bug 374605 - Unreasonable warning for enum-based switch statements
* bug 384870 - [compiler] @Deprecated annotation not detected if preceded by other annotation
* bug 393719 - [compiler] inconsistent warnings on iteration variables
- * Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
+ * Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Jesper S Moller - Contributions for
* bug 382721 - [1.8][compiler] Effectively final variables needs special treatment
+ * bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
+ * bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import java.util.HashMap;
+import java.util.Map;
+
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.lookup.*;
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding;
/**
@@ -780,8 +786,16 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
Annotation annotation = sourceAnnotations[i];
final Binding annotationRecipient = annotation.recipient;
if (annotationRecipient != null && recipient != null) {
- // only local and field can share annnotations
+ // only local and field can share annnotations and their types.
switch (recipient.kind()) {
+ case Binding.TYPE_USE:
+ if (annotations != null) {
+ // need to fill the instances array
+ for (int j = 0; j < length; j++) {
+ annotations[j] = sourceAnnotations[j].getCompilerAnnotation();
+ }
+ }
+ break;
case Binding.FIELD :
FieldBinding field = (FieldBinding) recipient;
field.tagBits = ((FieldBinding) annotationRecipient).tagBits;
@@ -828,6 +842,11 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
}
}
break;
+ default:
+ if (annotations != null) {
+ annotations[i] = annotation.getCompilerAnnotation();
+ }
+ break;
}
return annotations;
} else {
@@ -841,30 +860,66 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
}
if (copySE8AnnotationsToType)
- copySE8AnnotationsToType(scope, recipient, annotations);
+ copySE8AnnotationsToType(scope, recipient, sourceAnnotations);
+
+ if (annotations != null && length > 0 && recipient != null && recipient.isAnnotationType()) {
+ // See if this is meta-annotated as repeatable and if so validate constraints.
+ for (int i = 0; i < length; i++) {
+ Annotation annotation = sourceAnnotations[i];
+ MemberValuePair[] valuePairs = annotation.memberValuePairs();
+ ReferenceBinding annotationType = annotations[i] != null ? annotations[i].getAnnotationType() : null;
+ if (annotationType != null && annotationType.id == TypeIds.T_JavaLangAnnotationRepeatable && valuePairs != null && valuePairs.length > 0) {
+ annotation.checkRepeatableAnnotation(valuePairs[0], scope, valuePairs[0].compilerElementPair.value);
+ }
+ }
+ }
// check duplicate annotations
if (annotations != null && length > 1) {
AnnotationBinding[] distinctAnnotations = annotations; // only copy after 1st duplicate is detected
+ Map implicitContainerAnnotations = null;
for (int i = 0; i < length; i++) {
AnnotationBinding annotation = distinctAnnotations[i];
if (annotation == null) continue;
- TypeBinding annotationType = annotation.getAnnotationType();
+ ReferenceBinding annotationType = annotation.getAnnotationType();
boolean foundDuplicate = false;
for (int j = i+1; j < length; j++) {
AnnotationBinding otherAnnotation = distinctAnnotations[j];
if (otherAnnotation == null) continue;
if (otherAnnotation.getAnnotationType() == annotationType) {
- foundDuplicate = true;
- if (distinctAnnotations == annotations) {
- System.arraycopy(distinctAnnotations, 0, distinctAnnotations = new AnnotationBinding[length], 0, length);
+ if (annotationType.isRepeatableAnnotation()) {
+ ReferenceBinding resolvedContainer = annotationType.resolveContainerAnnotation();
+ if (resolvedContainer != null) {
+ // Since this is a repeated annotation, we need to check if the container is also used - so store it
+ // in a map of (container's ReferenceBinding -> the repeated source Annotation)
+ if (implicitContainerAnnotations == null) implicitContainerAnnotations = new HashMap(3);
+ implicitContainerAnnotations.put(resolvedContainer, sourceAnnotations[i]);
+ // Validate the repeated *use* of a repeatable annotation.
+ Annotation.checkContainingAnnotation(sourceAnnotations[i], scope, resolvedContainer, annotationType);
+ }
+ } else {
+ foundDuplicate = true;
+ if (distinctAnnotations == annotations) {
+ System.arraycopy(distinctAnnotations, 0, distinctAnnotations = new AnnotationBinding[length], 0, length);
+ }
+ distinctAnnotations[j] = null; // report it only once
+ scope.problemReporter().duplicateAnnotation(sourceAnnotations[j], scope.compilerOptions().sourceLevel);
}
- distinctAnnotations[j] = null; // report it only once
- scope.problemReporter().duplicateAnnotation(sourceAnnotations[j]);
}
}
if (foundDuplicate) {
- scope.problemReporter().duplicateAnnotation(sourceAnnotations[i]);
+ scope.problemReporter().duplicateAnnotation(sourceAnnotations[i], scope.compilerOptions().sourceLevel);
+ }
+ }
+ // Check for presence of repeating annotation together with the containing annotation
+ if (implicitContainerAnnotations != null) {
+ for (int i = 0; i < length; i++) {
+ if (distinctAnnotations[i] == null) continue;
+ Annotation annotation = sourceAnnotations[i];
+ ReferenceBinding annotationType = distinctAnnotations[i].getAnnotationType();
+ if (implicitContainerAnnotations.containsKey(annotationType)) {
+ scope.problemReporter().repeatedAnnotationWithContainer((Annotation) implicitContainerAnnotations.get(annotationType), annotation);
+ }
}
}
}
@@ -895,20 +950,31 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
/** When SE8 annotations feature in SE7 locations, they get attributed to the declared entity. Copy these to the type of the declared entity (field, local, argument etc.)
We leave in the annotation in the declared entity's binding as of now, i.e we do a copy not a transfer.
*/
- public static void copySE8AnnotationsToType(BlockScope scope, Binding recipient, AnnotationBinding[] annotations) {
+ public static void copySE8AnnotationsToType(BlockScope scope, Binding recipient, Annotation[] annotations) {
if (annotations != null && recipient.kind() != Binding.TYPE_USE) {
AnnotationBinding [] se8Annotations = null;
int se8count = 0;
+ long se8nullBits = 0;
+ Annotation se8NullAnnotation = null;
for (int i = 0, length = annotations.length; i < length; i++) {
- final ReferenceBinding annotationType = annotations[i].getAnnotationType();
+ AnnotationBinding annotation = annotations[i].getCompilerAnnotation();
+ if (annotation == null) continue;
+ final ReferenceBinding annotationType = annotation.getAnnotationType();
long metaTagBits = annotationType.getAnnotationTagBits();
if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) {
if (se8Annotations == null) {
- se8Annotations = new AnnotationBinding[] { annotations[i] };
+ se8Annotations = new AnnotationBinding[] { annotation };
se8count = 1;
} else {
System.arraycopy(se8Annotations, 0, se8Annotations = new AnnotationBinding[se8count + 1], 0, se8count);
- se8Annotations[se8count++] = annotations[i];
+ se8Annotations[se8count++] = annotation;
+ }
+ if (annotationType.id == TypeIds.T_ConfiguredAnnotationNonNull) {
+ se8nullBits = TagBits.AnnotationNonNull;
+ se8NullAnnotation = annotations[i];
+ } else if (annotationType.id == TypeIds.T_ConfiguredAnnotationNullable) {
+ se8nullBits = TagBits.AnnotationNullable;
+ se8NullAnnotation = annotations[i];
}
}
}
@@ -916,14 +982,11 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
switch (recipient.kind()) {
case Binding.LOCAL:
LocalVariableBinding local = (LocalVariableBinding) recipient;
- if (Annotation.isTypeUseCompatible(local.declaration.type, scope)) { // discard hybrid annotations on package qualified types.
+ TypeReference typeRef = local.declaration.type;
+ if (Annotation.isTypeUseCompatible(typeRef, scope)) { // discard hybrid annotations on package qualified types.
local.declaration.bits |= HasTypeAnnotations;
- final TypeBinding localType = local.type;
- TypeBinding oldLeafType = localType.leafComponentType();
- AnnotationBinding [][] goodies = new AnnotationBinding[local.declaration.type.getAnnotatableLevels()][];
- goodies[0] = se8Annotations; // @T X.Y.Z local; ==> @T should annotate X
- TypeBinding newLeafType = scope.environment().createAnnotatedType(oldLeafType, goodies);
- local.type = localType.isArrayType() ? scope.environment().createArrayType(newLeafType, localType.dimensions(), localType.getTypeAnnotations()) : newLeafType;
+ typeRef.bits |= HasTypeAnnotations;
+ local.type = mergeAnnotationsIntoType(scope, se8Annotations, se8nullBits, se8NullAnnotation, typeRef, local.type);
}
break;
case Binding.FIELD:
@@ -931,12 +994,9 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
SourceTypeBinding sourceType = (SourceTypeBinding) field.declaringClass;
FieldDeclaration fieldDeclaration = sourceType.scope.referenceContext.declarationOf(field);
if (Annotation.isTypeUseCompatible(fieldDeclaration.type, scope)) { // discard hybrid annotations on package qualified types.
- TypeBinding fieldType = field.type;
- TypeBinding oldLeafType = fieldType.leafComponentType();
- AnnotationBinding [][] goodies = new AnnotationBinding[fieldDeclaration.type.getAnnotatableLevels()][];
- goodies[0] = se8Annotations; // @T X.Y.Z field; ==> @T should annotate X
- TypeBinding newLeafType = scope.environment().createAnnotatedType(oldLeafType, goodies);
- field.type = fieldType.isArrayType() ? scope.environment().createArrayType(newLeafType, fieldType.dimensions(), fieldType.getTypeAnnotations()) : newLeafType;
+ fieldDeclaration.bits |= HasTypeAnnotations;
+ fieldDeclaration.type.bits |= HasTypeAnnotations;
+ field.type = mergeAnnotationsIntoType(scope, se8Annotations, se8nullBits, se8NullAnnotation, fieldDeclaration.type, field.type);
}
break;
case Binding.METHOD:
@@ -945,12 +1005,9 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
sourceType = (SourceTypeBinding) method.declaringClass;
MethodDeclaration methodDecl = (MethodDeclaration) sourceType.scope.referenceContext.declarationOf(method);
if (Annotation.isTypeUseCompatible(methodDecl.returnType, scope)) {
- final TypeBinding returnType = method.returnType;
- TypeBinding oldLeafType = returnType.leafComponentType();
- AnnotationBinding [][] goodies = new AnnotationBinding[methodDecl.returnType.getAnnotatableLevels()][];
- goodies[0] = se8Annotations;
- TypeBinding newLeafType = scope.environment().createAnnotatedType(oldLeafType, goodies);
- method.returnType = returnType.isArrayType() ? scope.environment().createArrayType(newLeafType, returnType.dimensions(), returnType.getTypeAnnotations()) : newLeafType;
+ methodDecl.bits |= HasTypeAnnotations;
+ methodDecl.returnType.bits |= HasTypeAnnotations;
+ method.returnType = mergeAnnotationsIntoType(scope, se8Annotations, se8nullBits, se8NullAnnotation, methodDecl.returnType, method.returnType);
}
}
break;
@@ -959,6 +1016,30 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
}
}
+ private static TypeBinding mergeAnnotationsIntoType(BlockScope scope, AnnotationBinding[] se8Annotations, long se8nullBits, Annotation se8NullAnnotation,
+ TypeReference typeRef, TypeBinding existingType)
+ {
+ if (existingType == null || !existingType.isValidBinding()) return existingType;
+ TypeReference unionRef = typeRef.isUnionType() ? ((UnionTypeReference) typeRef).typeReferences[0] : null;
+
+ long prevNullBits = existingType.tagBits & TagBits.AnnotationNullMASK;
+ if (se8nullBits != 0 && prevNullBits != se8nullBits && ((prevNullBits | se8nullBits) == TagBits.AnnotationNullMASK)) {
+ scope.problemReporter().contradictoryNullAnnotations(se8NullAnnotation);
+ }
+ TypeBinding oldLeafType = (unionRef == null) ? existingType.leafComponentType() : unionRef.resolvedType;
+ AnnotationBinding [][] goodies = new AnnotationBinding[typeRef.getAnnotatableLevels()][];
+ goodies[0] = se8Annotations; // @T X.Y.Z local; ==> @T should annotate X
+ TypeBinding newLeafType = scope.environment().createAnnotatedType(oldLeafType, goodies);
+
+ if (unionRef == null) {
+ typeRef.resolvedType = existingType.isArrayType() ? scope.environment().createArrayType(newLeafType, existingType.dimensions(), existingType.getTypeAnnotations()) : newLeafType;
+ } else {
+ unionRef.resolvedType = newLeafType;
+ unionRef.bits |= HasTypeAnnotations;
+ }
+ return typeRef.resolvedType;
+ }
+
/**
* Figures if @Deprecated annotation is specified, do not resolve entire annotations.
*/
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
index e64483fd3..c0907ae76 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AbstractMethodDeclaration.java
@@ -25,6 +25,7 @@
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
* Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
* Bug 403216 - [1.8][null] TypeReference#captureTypeAnnotations treats type annotations as type argument annotations
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -987,8 +988,9 @@ public abstract class AbstractMethodDeclaration
} else {
int length = this.binding.parameters.length;
for (int i=0; i<length; i++) {
- if (!this.scope.validateNullAnnotation(this.binding.parameters[i].tagBits, this.arguments[i].type, this.arguments[i].annotations))
- this.binding.parameters[i] = this.binding.parameters[i].unannotated();
+ this.scope.validateNullAnnotation(this.binding.parameters[i].tagBits, this.arguments[i].type, this.arguments[i].annotations);
+// TODO(stephan) remove once we're sure:
+// this.binding.parameters[i] = this.binding.parameters[i].unannotated();
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
index 187ef9bb6..0c012ebe0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java
@@ -27,9 +27,10 @@
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
* bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking
* Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Jesper S Moller <jesper@selskabet.org> - Contributions for
* bug 378674 - "The method can be declared as static" is wrong
- * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
+ * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
* Bug 409245 - [1.8][compiler] Type annotations dropped when call is routed through a synthetic bridge method
*******************************************************************************/
@@ -366,7 +367,7 @@ public TypeBinding resolveType(BlockScope scope) {
this.type.bits |= IsAllocationType;
// SH}
this.resolvedType = this.type.resolveType(scope, true /* check bounds*/);
- this.resolvedType = checkIllegalNullAnnotation(scope, this.resolvedType);
+ checkIllegalNullAnnotation(scope, this.resolvedType);
checkParameterizedAllocation: {
if (this.type instanceof ParameterizedQualifiedTypeReference) { // disallow new X<String>.Y<Integer>()
ReferenceBinding currentType = (ReferenceBinding)this.resolvedType;
@@ -591,19 +592,16 @@ public TypeBinding resolveType(BlockScope scope) {
/**
* Check if 'allocationType' illegally has a top-level null annotation.
- * If so: report an error and return the unannotated variant.
*/
-TypeBinding checkIllegalNullAnnotation(BlockScope scope, TypeBinding allocationType) {
+void checkIllegalNullAnnotation(BlockScope scope, TypeBinding allocationType) {
if (allocationType != null) {
// only check top-level null annotation (annots on details are OK):
long nullTagBits = allocationType.tagBits & TagBits.AnnotationNullMASK;
if (nullTagBits != 0) {
Annotation annotation = this.type.findAnnotation(nullTagBits);
scope.problemReporter().nullAnnotationUnsupportedLocation(annotation);
- return allocationType.unannotated();
}
}
- return allocationType;
}
public TypeBinding[] inferElidedTypes(ReferenceBinding allocationType, ReferenceBinding enclosingType, TypeBinding[] argumentTypes, final BlockScope scope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
index c295955d2..e9713750b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
@@ -21,11 +21,15 @@
* Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099
* Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
* Bug 415850 - [1.8] Ensure RunJDTCoreTests can cope with null annotations enabled
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
* Bug 409517 - [1.8][compiler] Type annotation problems on more elaborate array references
* Bug 415397 - [1.8][compiler] Type Annotations on wildcard type argument dropped
* Bug 414384 - [1.8] type annotation on abbreviated inner class is not marked as inner type
+ * Jesper S Moller <jesper@selskabet.org> - Contributions for
+ * Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
+# Bug 412151 - [1.8][compiler] Check repeating annotation's collection type
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -53,453 +57,145 @@ public abstract class Annotation extends Expression {
* Return the location for the corresponding annotation inside the type reference, <code>null</code> if none.
*/
public static int[] getLocations(
- final TypeReference reference,
- final Annotation[] primaryAnnotation,
- final Annotation annotation,
- final Annotation[][] annotationsOnDimensionsOnExpression,
- final int dimensions) {
+ final Expression reference,
+ final Annotation annotation) {
class LocationCollector extends ASTVisitor {
Stack typePathEntries;
- Annotation currentAnnotation;
- boolean search = true;
+ Annotation searchedAnnotation;
+ boolean continueSearch = true;
public LocationCollector(Annotation currentAnnotation) {
this.typePathEntries = new Stack();
- this.currentAnnotation = currentAnnotation;
+ this.searchedAnnotation = currentAnnotation;
}
- public boolean visit(ParameterizedSingleTypeReference typeReference, BlockScope scope) {
- if (!this.search) return false;
-
- Annotation[][] annotationsOnDimensions = typeReference.annotationsOnDimensions;
- if (annotationsOnDimensions != null) {
- for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) {
- Annotation[] annotations = annotationsOnDimensions[i];
- if (annotations != null) {
- for (int j = 0, max2 = annotations.length; j < max2; j++) {
- Annotation current = annotations[j];
- if (current == this.currentAnnotation) {
- // found it, push any relevant type path entries
- for (int k = 0; k < i; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
- }
- this.search = false;
- return false;
- }
- }
- }
-
- }
- }
-
- // Example cases handled here: @B(1) List<String>[]
- Annotation[][] annotations = typeReference.annotations;
- if (annotations == null) {
- annotations = new Annotation[][] { primaryAnnotation };
- }
- int annotationsLevels = annotations.length;
- for (int i = 0; i < annotationsLevels; i++) {
- Annotation [] current = annotations[i];
- int annotationsLength = current == null ? 0 : current.length;
- for (int j = 0; j < annotationsLength; j++) {
- if (current[j] == this.currentAnnotation) {
- this.search = false;
- // Found it, insert any necessary type path elements
- for (int k = 0; k < typeReference.dimensions; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
- }
- return false;
- }
+ private int[] computeNestingDepth(TypeReference typeReference) {
+ TypeBinding type = typeReference.resolvedType == null ? null : typeReference.resolvedType.leafComponentType();
+ int[] nestingDepths = new int[typeReference.getAnnotatableLevels()];
+ if (type != null && type.isNestedType()) {
+ int depth = 0;
+ TypeBinding currentType = type;
+ while (currentType != null) {
+ depth += (currentType.isStatic()) ? 0 : 1;
+ currentType = currentType.enclosingType();
}
- }
-
- // If a type argument is annotated it is necessary jump past the array elements
- if (typeReference.dimensions != 0) {
- for (int k = 0, maxk = typeReference.dimensions; k < maxk; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
- }
- }
- TypeReference[] typeReferences = typeReference.typeArguments;
- for (int i = 0, max = typeReferences.length; i < max; i++) {
- this.typePathEntries.add(new int[]{3,i});
- typeReferences[i].traverse(this, scope);
- if (!this.search) {
- return false;
- } else {
- this.typePathEntries.pop();
+ // Work backwards computing whether a INNER_TYPE entry is required for each level
+ int counter = nestingDepths.length - 1;
+ while (type != null && counter >= 0) {
+ nestingDepths[counter--] = depth;
+ depth -= type.isStatic() ? 0 : 1;
+ type = type.enclosingType();
}
}
- if (typeReference.dimensions != 0) {
- for (int k = 0, maxk = typeReference.dimensions; k < maxk; k++) {
- this.typePathEntries.pop();
- }
- }
- return true;
+ return nestingDepths;
}
+
- public boolean visit(SingleTypeReference typeReference, BlockScope scope) {
- if (!this.search) return false;
-
- // Example case handled by this block: X[][] x = new @A X @B [] @C[]{ { null }, { null } };
- if (dimensions != 0 && annotationsOnDimensionsOnExpression != null) {
- for (int i = 0, max = annotationsOnDimensionsOnExpression.length; i < max; i++) {
- Annotation[] annotations = annotationsOnDimensionsOnExpression[i];
- if (annotations != null) {
- for (int j = 0, max2 = annotations.length; j < max2; j++) {
- Annotation current = annotations[j];
- if (current == this.currentAnnotation) {
- this.search = false;
- // Found it, insert relevant type path elements
- for (int k = 0, maxk = i; k < maxk; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
- }
- return false;
- }
- }
- }
- }
- }
-
- if (dimensions != 0) {
- for (int k = 0; k < dimensions; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
- }
- }
- Annotation[][] annotations = typeReference.annotations;
- if (annotations == null) {
- annotations = new Annotation[][] { primaryAnnotation };
+ private void inspectAnnotations(Annotation [] annotations) {
+ for (int i = 0, length = annotations == null ? 0 : annotations.length; this.continueSearch && i < length; i++) {
+ if (annotations[i] == this.searchedAnnotation)
+ this.continueSearch = false;
}
- int annotationsLevels = annotations.length;
- for (int i = 0; i < annotationsLevels; i++) {
- Annotation [] current = annotations[i];
- int annotationsLength = current == null ? 0 : current.length;
- for (int j = 0; j < annotationsLength; j++) {
- if (current[j] == this.currentAnnotation) {
- // Found
- this.search = false;
- int depth = getInnerDepth(typeReference.resolvedType);
- if (depth != 0) {
- for (int k = 0; k<depth; k++) {
- this.typePathEntries.add(TYPE_PATH_INNER_TYPE);
- }
- }
- return false;
- }
- }
- }
- if (dimensions != 0) {
- for (int k = 0; k < dimensions; k++) {
- this.typePathEntries.pop();
- }
- }
- return false;
}
- public boolean visit(ArrayTypeReference typeReference, BlockScope scope) {
- if (!this.search) return false;
-
- Annotation[][] annotationsOnDimensions = typeReference.annotationsOnDimensions;
- if (annotationsOnDimensions != null) {
- for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) {
- Annotation[] annotations = annotationsOnDimensions[i];
- if (annotations != null) {
- for (int j = 0, max2 = annotations.length; j < max2; j++) {
- Annotation current = annotations[j];
- if (current == this.currentAnnotation) {
- for (int k = 0; k < i; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
- }
- this.search = false;
- return false;
- }
- }
- }
-
- }
+ private void inspectArrayDimensions(Annotation [][] annotationsOnDimensions, int dimensions) {
+ for (int i = 0; this.continueSearch && i < dimensions; i++) {
+ Annotation[] annotations = annotationsOnDimensions == null ? null : annotationsOnDimensions[i];
+ inspectAnnotations(annotations);
+ if (!this.continueSearch) return;
+ this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
}
- Annotation[][] annotations = typeReference.annotations;
- if (annotations == null) {
- annotations = new Annotation[][] { primaryAnnotation };
- }
- int annotationsLevels = annotations.length;
- for (int i = 0; i < annotationsLevels; i++) {
- Annotation [] current = annotations[i];
- int annotationsLength = current == null ? 0 : current.length;
- for (int j = 0; j < annotationsLength; j++) {
- if (current[j] == this.currentAnnotation) {
- for (int k = 0, maxk=typeReference.dimensions; k < maxk; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
- }
- this.search = false;
- return false;
- }
- }
- }
- return true;
}
- public boolean visit(ArrayQualifiedTypeReference typeReference, BlockScope scope) {
- if (!this.search) return false;
- Annotation[][] annotationsOnDimensions = typeReference.annotationsOnDimensions;
- if (annotationsOnDimensions != null) {
- for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) {
- Annotation[] annotations = annotationsOnDimensions[i];
- if (annotations != null) {
- for (int j = 0, max2 = annotations.length; j < max2; j++) {
- Annotation current = annotations[j];
- if (current == this.currentAnnotation) {
- this.search = false;
- // Found it, insert relevant type path elements
- for (int k = 0, maxk = i; k < maxk; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
- }
- return false;
- }
- }
- }
- }
- }
-
- if (primaryAnnotation != null) {
- for (int i = 0, max = primaryAnnotation.length; i < max; i++) {
- if (primaryAnnotation[i] == this.currentAnnotation) {
- this.search = false;
- for (int k = 0, maxk = typeReference.dimensions; k < maxk; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
- }
- return false;
- }
- }
- }
-
- Annotation[][] annotations = typeReference.annotations;
- if (annotations != null) {
- int annotationsLevels = annotations.length;
- for (int i = 0; i < annotationsLevels; i++) {
- Annotation [] current = annotations[i];
- int annotationsLength = current == null ? 0 : current.length;
- for (int j = 0; j < annotationsLength; j++) {
- if (current[j] == this.currentAnnotation) {
- this.search = false;
- for (int k = 0, maxk = typeReference.dimensions; k < maxk; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
- }
- // depth allows for references like: one.two.three.@B Foo[]
- // the inner_type elements to the type path depend on the types not the package qualifiers
- int depth = getInnerDepth(typeReference.resolvedType);
- if (depth != 0) {
- for (int k = 0; k < depth; k++) {
- this.typePathEntries.push(TYPE_PATH_INNER_TYPE);
- }
- }
- return false;
- }
- }
- }
+ private void inspectTypeArguments(TypeReference[] typeReferences) {
+ for (int i = 0, length = typeReferences == null ? 0 : typeReferences.length; this.continueSearch && i < length; i++) {
+ int size = this.typePathEntries.size();
+ this.typePathEntries.add(new int[]{3,i});
+ typeReferences[i].traverse(this, (BlockScope) null);
+ if (!this.continueSearch) return;
+ this.typePathEntries.setSize(size);
}
- return true;
}
- public boolean visit(ParameterizedQualifiedTypeReference typeReference, BlockScope scope) {
- if (!this.search) return false;
-
- // Example case handled by this block: java.util.List<String>[]@A[]
- Annotation[][] annotationsOnDimensions = typeReference.annotationsOnDimensions;
- if (annotationsOnDimensions != null) {
- for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) {
- Annotation[] annotations = annotationsOnDimensions[i];
- if (annotations != null) {
- for (int j = 0, max2 = annotations.length; j < max2; j++) {
- Annotation current = annotations[j];
- if (current == this.currentAnnotation) {
- this.search = false;
- // Found it, insert relevant type path elements
- for (int k = 0, maxk = i; k < maxk; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
- }
- return false;
- }
- }
- }
- }
- }
-
- boolean[] needsInnerEntryInfo = computeInnerEntryInfo(typeReference);
-
- // Example cases handled by this block:
- // java.util.@A List<String>[][], com.demo.@A Outer.@B Inner<String>, java.util.Map.@A Entry<String,String>
- Annotation[][] annotations = typeReference.annotations;
- if (annotations == null) {
- annotations = new Annotation[][] { primaryAnnotation };
- }
- int annotationsLevels = annotations.length;
- for (int i = 0; i < annotationsLevels; i++) {
- Annotation [] current = annotations[i];
- int annotationsLength = current == null ? 0 : current.length;
- for (int j = 0; j < annotationsLength; j++) {
- if (current[j] == this.currentAnnotation) {
- this.search = false;
- // Found, insert any relevant type path elements
- for (int k = 0, maxk = typeReference.dimensions; k < maxk; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
+ public boolean visit(TypeReference typeReference, BlockScope scope) {
+ if (this.continueSearch) {
+ inspectArrayDimensions(typeReference.getAnnotationsOnDimensions(), typeReference.dimensions());
+ if (this.continueSearch) {
+ int[] nestingDepths = computeNestingDepth(typeReference);
+ Annotation[][] annotations = typeReference.annotations;
+ TypeReference [][] typeArguments = typeReference.getTypeArguments();
+ int levels = typeReference.getAnnotatableLevels();
+ int size = this.typePathEntries.size();
+ for (int i = levels - 1; this.continueSearch && i >= 0; i--) { // traverse outwards, see comment below about type annotations from SE7 locations.
+ this.typePathEntries.setSize(size);
+ for (int j = 0, depth = nestingDepths[i]; j < depth; j++)
+ this.typePathEntries.add(TYPE_PATH_INNER_TYPE);
+ if (annotations != null)
+ inspectAnnotations(annotations[i]);
+ if (this.continueSearch && typeArguments != null) {
+ inspectTypeArguments(typeArguments[i]);
}
- // Found, insert any relevant type path elements
- if (needsInnerEntryInfo != null) {
- for (int k = 0; k <= i; k++) {
- if (needsInnerEntryInfo[k]) {
- this.typePathEntries.push(TYPE_PATH_INNER_TYPE);
- }
- }
- }
- return false;
- }
- }
- }
-
- // Example cases handled by this block:
- // java.util.List<@A String>
- if (typeReference.dimensions != 0) {
- for (int k = 0, maxk = typeReference.dimensions; k < maxk; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
- }
- }
- int toPop = 0;
- for (int i = 0, max = typeReference.typeArguments.length; i < max; i++) {
- TypeReference[] typeArgumentsForComponent = typeReference.typeArguments[i];
- if (needsInnerEntryInfo != null && needsInnerEntryInfo[i]) {
- this.typePathEntries.push(TYPE_PATH_INNER_TYPE);
- toPop++;
- }
- if (typeArgumentsForComponent != null) {
- for (int j = 0, max2 = typeArgumentsForComponent.length; j < max2; j++) {
- this.typePathEntries.push(new int[]{3,j});
- typeArgumentsForComponent[j].traverse(this,scope);
- if (!this.search) return false;
- this.typePathEntries.pop();
}
}
}
- toPop += typeReference.dimensions;
- for (int k = 0, maxk = toPop; k < maxk; k++) {
- this.typePathEntries.pop();
- }
- return true;
+ return false; // if annotation is not found in the type reference, it must be one from SE7 location, typePathEntries captures the proper path entries for them.
+ }
+ public boolean visit(SingleTypeReference typeReference, BlockScope scope) {
+ return visit((TypeReference) typeReference, scope);
}
- public boolean visit(Wildcard typeReference, BlockScope scope) {
- if (!this.search) return false;
-
- // This block handles List<@Foo ? extends Serializable>
- Annotation[][] annotations = typeReference.annotations;
- if (annotations == null) {
- annotations = new Annotation[][] { primaryAnnotation };
- }
- int annotationsLevels = annotations.length;
- for (int i = 0; i < annotationsLevels; i++) {
- Annotation [] current = annotations[i];
- int annotationsLength = current == null ? 0 : current.length;
- for (int j = 0; j < annotationsLength; j++) {
- if (current[j] == this.currentAnnotation) {
- this.search = false;
- return false;
- }
- }
- }
+ public boolean visit(ArrayTypeReference typeReference, BlockScope scope) {
+ return visit((TypeReference) typeReference, scope);
+ }
+
+ public boolean visit(ParameterizedSingleTypeReference typeReference, BlockScope scope) {
+ return visit((TypeReference) typeReference, scope);
+ }
- TypeReference bound = typeReference.bound;
- this.typePathEntries.push(TYPE_PATH_ANNOTATION_ON_WILDCARD_BOUND);
- bound.traverse(this, scope);
- if (!this.search) {
- return false;
- }
- this.typePathEntries.pop();
- return true;
+ public boolean visit(QualifiedTypeReference typeReference, BlockScope scope) {
+ return visit((TypeReference) typeReference, scope);
}
- private boolean[] computeInnerEntryInfo(QualifiedTypeReference typeReference) {
- ReferenceBinding resolvedType = (ReferenceBinding)
- (typeReference.resolvedType instanceof ArrayBinding ? typeReference.resolvedType.leafComponentType() : typeReference.resolvedType);
- boolean[] needsInnerEntryInfo = null;
- if (resolvedType != null && resolvedType.isNestedType()) {
- // Work backwards computing whether a INNER_TYPE entry is required for each level
- needsInnerEntryInfo = new boolean[typeReference.tokens.length];
- int counter = needsInnerEntryInfo.length - 1;
- ReferenceBinding type = resolvedType;//resolvedType.enclosingType();
- while (type != null && counter > 0) {
- needsInnerEntryInfo[counter--] = !type.isStatic();
- type = type.enclosingType();
- }
- }
- return needsInnerEntryInfo;
+ public boolean visit(ArrayQualifiedTypeReference typeReference, BlockScope scope) {
+ return visit((TypeReference) typeReference, scope);
}
- private int getInnerDepth(TypeBinding resolvedType) {
- ReferenceBinding type = null;
- if (resolvedType instanceof ReferenceBinding) {
- type = (ReferenceBinding)resolvedType;
- } else if (resolvedType instanceof ArrayBinding) {
- TypeBinding leafComponentType = ((ArrayBinding)resolvedType).leafComponentType;
- if (leafComponentType instanceof ReferenceBinding) {
- type = (ReferenceBinding)leafComponentType;
- }
- }
- int depth = 0;
- while (type != null) {
- depth += (type.isStatic())?0:1;
- type = type.enclosingType();
- }
- return depth;
+ public boolean visit(ParameterizedQualifiedTypeReference typeReference, BlockScope scope) {
+ return visit((TypeReference) typeReference, scope);
}
- public boolean visit(QualifiedTypeReference typeReference, BlockScope scope) {
- if (!this.search) return false;
- boolean[] needsInnerEntryInfo = computeInnerEntryInfo(typeReference);
-
- if (dimensions != 0) {
- for (int k = 0; k < dimensions; k++) {
- this.typePathEntries.push(TYPE_PATH_ELEMENT_ARRAY);
- }
- }
-
- // Example cases handled by this block:
- // java.util.@A List, com.demo.@A Outer.@B Inner, java.util.Map.@A Entry
- Annotation[][] annotations = typeReference.annotations;
- if (annotations == null) {
- annotations = new Annotation[][] { primaryAnnotation };
- }
- int annotationsLevels = annotations.length;
- for (int i = 0; i < annotationsLevels; i++) {
- Annotation [] current = annotations[i];
- int annotationsLength = current == null ? 0 : current.length;
- for (int j = 0; j < annotationsLength; j++) {
- if (current[j] == this.currentAnnotation) {
- this.search = false;
- // Found, insert any relevant type path elements
- if (needsInnerEntryInfo != null) {
- for (int k = 0; k <= i; k++) {
- if (needsInnerEntryInfo[k]) {
- this.typePathEntries.push(TYPE_PATH_INNER_TYPE);
- }
- }
- }
- return false;
- }
+ public boolean visit(Wildcard typeReference, BlockScope scope) {
+ visit((TypeReference) typeReference, scope);
+ if (this.continueSearch) {
+ TypeReference bound = typeReference.bound;
+ if (bound != null) {
+ int size = this.typePathEntries.size();
+ this.typePathEntries.push(TYPE_PATH_ANNOTATION_ON_WILDCARD_BOUND);
+ bound.traverse(this, scope);
+ if (this.continueSearch)
+ this.typePathEntries.setSize(size);
}
}
- if (dimensions != 0) {
- for (int k = 0; k < dimensions; k++) {
- this.typePathEntries.pop();
+ return false;
+ }
+
+ public boolean visit(ArrayAllocationExpression allocationExpression, BlockScope scope) {
+ if (this.continueSearch) {
+ inspectArrayDimensions(allocationExpression.getAnnotationsOnDimensions(), allocationExpression.dimensions.length);
+ if (this.continueSearch) {
+ allocationExpression.type.traverse(this, scope);
}
+ if (this.continueSearch) throw new IllegalStateException();
}
- return true;
+ return false;
}
-
+
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer
.append("search location for ") //$NON-NLS-1$
- .append(this.currentAnnotation)
+ .append(this.searchedAnnotation)
.append("\ncurrent type_path entries : "); //$NON-NLS-1$
for (int i = 0, maxi = this.typePathEntries.size(); i < maxi; i++) {
int[] typePathEntry = (int[]) this.typePathEntries.get(i);
@@ -711,6 +407,155 @@ public abstract class Annotation extends Expression {
return tagBits;
}
+ static String getRetentionName(long tagBits) {
+ if ((tagBits & TagBits.AnnotationRuntimeRetention) == TagBits.AnnotationRuntimeRetention) {
+ // TagBits.AnnotationRuntimeRetention combines both TagBits.AnnotationClassRetention & TagBits.AnnotationSourceRetention
+ return new String(UPPER_RUNTIME);
+ } else if ((tagBits & TagBits.AnnotationSourceRetention) != 0) {
+ return new String(UPPER_SOURCE);
+ } else {
+ return new String(TypeConstants.UPPER_CLASS);
+ }
+ }
+
+ private static long getAnnotationRetention(ReferenceBinding binding) {
+ long retention = binding.getAnnotationTagBits() & TagBits.AnnotationRetentionMASK;
+ // Retention defaults to CLASS
+ return retention != 0 ? retention : TagBits.AnnotationClassRetention;
+ }
+
+ public void checkRepeatableAnnotation(ASTNode valueAttribute, Scope scope, Object containingBinding) {
+ if (! (this.recipient instanceof ReferenceBinding && containingBinding instanceof ReferenceBinding)) return; // Has deeper problems...
+ ReferenceBinding containing = (ReferenceBinding)containingBinding;
+ ReferenceBinding repeatableAnnotation = (ReferenceBinding) this.recipient;
+ repeatableAnnotation.setContainingAnnotation(containing);
+
+ checkContainingAnnotation(valueAttribute, scope, containing, repeatableAnnotation);
+ }
+
+ public static void checkContainingAnnotation(ASTNode markerNode, Scope scope, ReferenceBinding container, ReferenceBinding repeatableAnnotation) {
+ MethodBinding[] annotationMethods = container.methods();
+ boolean sawValue = false;
+ for (int i = 0, length = annotationMethods.length; i < length; ++i) {
+ MethodBinding method = annotationMethods[i];
+ if (CharOperation.equals(method.selector, TypeConstants.VALUE)) {
+ sawValue = true;
+ if (method.returnType.isArrayType() && method.returnType.dimensions() == 1) {
+ ArrayBinding array = (ArrayBinding) method.returnType;
+ if (TypeBinding.equalsEquals(array.elementsType(), repeatableAnnotation)) continue;
+ }
+ scope.problemReporter().containingAnnotationHasWrongValueType(markerNode, container, repeatableAnnotation, method.returnType);
+ } else {
+ // Not the value() - must have default (or else isn't suitable as container
+ if ((method.modifiers & ClassFileConstants.AccAnnotationDefault) == 0) {
+ scope.problemReporter().containingAnnotationHasNonDefaultMembers(markerNode, container, method.selector);
+ }
+ }
+ }
+ if (!sawValue) {
+ scope.problemReporter().containingAnnotationMustHaveValue(markerNode, container);
+ }
+
+ checkContainingAnnotationRetention(markerNode, scope, container, repeatableAnnotation);
+ if (markerNode instanceof Annotation)
+ checkContainingAnnotationTarget((Annotation) markerNode, (BlockScope) scope, (TypeBinding) container, repeatableAnnotation);
+ else
+ checkContainingAnnotationTarget(markerNode, scope, container, repeatableAnnotation);
+ checkContaintAnnotationDocumented(markerNode, scope, container, repeatableAnnotation);
+ checkContaintAnnotationInherited(markerNode, scope, container, repeatableAnnotation);
+ }
+
+ // This is for error reporting for bad targets at the repeated annotation use site (as opposed to repeatable annotation type declaration site) - Leads to better message.
+ public static void checkContainingAnnotationTarget(Annotation annotation, BlockScope scope, TypeBinding containerAnnotationType, TypeBinding annotationType) {
+ // check (meta)target compatibility
+ if (!annotationType.isValidBinding()) {
+ // no need to check annotation usage if missing
+ return;
+ }
+ if (! isAnnotationTargetAllowed(annotation, scope, containerAnnotationType, annotation.recipient.kind())) {
+ scope.problemReporter().disallowedTargetForContainerAnnotation(annotation, containerAnnotationType);
+ }
+ }
+
+ // This is for error reporting for bad targets at annotation type declaration site (as opposed to the repeat site)
+ private static void checkContainingAnnotationTarget(ASTNode markerNode, Scope scope, ReferenceBinding container, ReferenceBinding repeatableAnnotation) {
+ long tagBits = repeatableAnnotation.getAnnotationTagBits();
+ if ((tagBits & TagBits.AnnotationTargetMASK) != 0) {
+ long containingTagBits = container.getAnnotationTagBits();
+ if ((containingTagBits & TagBits.AnnotationTargetMASK) == 0) {
+ scope.problemReporter().repeatableAnnotationHasTargets(markerNode, repeatableAnnotation, container);
+ } else {
+ final long targets = tagBits & TagBits.AnnotationTargetMASK;
+ final long containingTargets = containingTagBits & TagBits.AnnotationTargetMASK;
+
+ if ((containingTargets & ~targets) != 0) {
+ class MissingTargetBuilder {
+ StringBuffer targetBuffer = new StringBuffer();
+ void check(long targetMask, char[] targetName) {
+ if ((containingTargets & targetMask & ~targets) != 0) {
+ add(targetName);
+ }
+ }
+ void checkAnnotationType(char[] targetName) {
+ if ((containingTargets & TagBits.AnnotationForAnnotationType) != 0 &&
+ ((targets & (TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType))) == 0) {
+ add(targetName);
+ }
+ }
+ private void add(char[] targetName) {
+ if (this.targetBuffer.length() != 0) {
+ this.targetBuffer.append(", "); //$NON-NLS-1$
+ }
+ this.targetBuffer.append(targetName);
+ }
+ public String toString() {
+ return this.targetBuffer.toString();
+ }
+ public boolean hasError() {
+ return this.targetBuffer.length() != 0;
+ }
+ }
+ MissingTargetBuilder builder = new MissingTargetBuilder();
+
+ builder.check(TagBits.AnnotationForType, TypeConstants.TYPE);
+ builder.check(TagBits.AnnotationForField, TypeConstants.UPPER_FIELD);
+ builder.check(TagBits.AnnotationForMethod, TypeConstants.UPPER_METHOD);
+ builder.check(TagBits.AnnotationForParameter, TypeConstants.UPPER_PARAMETER);
+ builder.check(TagBits.AnnotationForConstructor, TypeConstants.UPPER_CONSTRUCTOR);
+ builder.check(TagBits.AnnotationForLocalVariable, TypeConstants.UPPER_LOCAL_VARIABLE);
+ builder.checkAnnotationType(TypeConstants.UPPER_ANNOTATION_TYPE);
+ builder.check(TagBits.AnnotationForPackage, TypeConstants.UPPER_PACKAGE);
+ builder.check(TagBits.AnnotationForTypeParameter, TypeConstants.TYPE_PARAMETER_TARGET);
+ builder.check(TagBits.AnnotationForTypeUse, TypeConstants.TYPE_USE_TARGET);
+ if (builder.hasError()) {
+ scope.problemReporter().repeatableAnnotationTargetMismatch(markerNode, repeatableAnnotation, container, builder.toString());
+ }
+ }
+ }
+ }
+ }
+
+ private static void checkContaintAnnotationDocumented(ASTNode markerNode, Scope scope, ReferenceBinding containing, ReferenceBinding repeatableAnnotation) {
+ if ((repeatableAnnotation.getAnnotationTagBits() & TagBits.AnnotationDocumented) != 0 && (containing.getAnnotationTagBits() & TagBits.AnnotationDocumented) == 0) {
+ scope.problemReporter().repeatableAnnotationIsDocumented(markerNode, repeatableAnnotation, containing);
+ }
+ }
+
+ private static void checkContaintAnnotationInherited(ASTNode markerNode, Scope scope, ReferenceBinding containing, ReferenceBinding repeatableAnnotation) {
+ if ((repeatableAnnotation.getAnnotationTagBits() & TagBits.AnnotationInherited) != 0 && (containing.getAnnotationTagBits() & TagBits.AnnotationInherited) == 0) {
+ scope.problemReporter().repeatableAnnotationIsInherited(markerNode, repeatableAnnotation, containing);
+ }
+ }
+
+ private static void checkContainingAnnotationRetention(ASTNode markerNode, Scope scope, ReferenceBinding container, ReferenceBinding repeatableAnnotation) {
+ long annotationBits = getAnnotationRetention(repeatableAnnotation);
+ long containerBits = getAnnotationRetention(container);
+ // Due to clever layout of the bits, we can compare the absolute value directly
+ if (containerBits < annotationBits) {
+ scope.problemReporter().containingAnnotationHasShorterRetention(markerNode, repeatableAnnotation, getRetentionName(annotationBits), container, getRetentionName(containerBits));
+ }
+ }
+
public AnnotationBinding getCompilerAnnotation() {
return this.compilerAnnotation;
}
@@ -1012,159 +857,149 @@ public abstract class Annotation extends Expression {
break;
case Binding.LOCAL :
LocalVariableBinding variable = (LocalVariableBinding) this.recipient;
- if (scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_8) {
- variable.tagBits |= tagBits;
- if ((variable.tagBits & TagBits.AnnotationNullMASK) == TagBits.AnnotationNullMASK) {
- scope.problemReporter().contradictoryNullAnnotations(this);
- variable.tagBits &= ~TagBits.AnnotationNullMASK; // avoid secondary problems
- }
- } else if (variable.type != null) {
- // bits not relating to null analysis go into the variable:
- variable.tagBits |= tagBits & ~TagBits.AnnotationNullMASK;
- // null bits go into the type:
- long nullTagBits = tagBits & TagBits.AnnotationNullMASK;
- if (nullTagBits != 0) {
- if (variable.type.isBaseType()) {
- scope.problemReporter().illegalAnnotationForBaseType(this, variable.type);
- } else if (variable.declaration.type instanceof QualifiedTypeReference) {
- scope.problemReporter().nullAnnotationUnsupportedLocation(this);
- } else if (nullTagBits != (variable.type.tagBits & TagBits.AnnotationNullMASK)) {
- if (((variable.type.tagBits & TagBits.AnnotationNullMASK) | nullTagBits ) == TagBits.AnnotationNullMASK) {
- scope.problemReporter().contradictoryNullAnnotations(this);
- variable.type = variable.type.unannotated();
- }
- }
- }
+ variable.tagBits |= tagBits;
+ if ((variable.tagBits & TagBits.AnnotationNullMASK) == TagBits.AnnotationNullMASK) {
+ scope.problemReporter().contradictoryNullAnnotations(this);
+ variable.tagBits &= ~TagBits.AnnotationNullMASK; // avoid secondary problems
}
if ((tagBits & TagBits.AnnotationSuppressWarnings) != 0) {
- LocalDeclaration localDeclaration = variable.declaration;
+ LocalDeclaration localDeclaration = variable.declaration;
recordSuppressWarnings(scope, localDeclaration.declarationSourceStart, localDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings);
}
break;
}
}
- // check (meta)target compatibility
- checkTargetCompatibility: {
- if (!annotationType.isValidBinding()) {
- // no need to check annotation usage if missing
- break checkTargetCompatibility;
- }
+ checkAnnotationTarget(this, scope, annotationType, kind);
+ }
+ return this.resolvedType;
+ }
- long metaTagBits = annotationType.getAnnotationTagBits(); // could be forward reference
- if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) {
- // does not specify any target restriction - all locations supported in Java 7 and before are possible
- if (kind == Binding.TYPE_PARAMETER || kind == Binding.TYPE_USE) {
- scope.problemReporter().explitAnnotationTargetRequired(this);
- }
- break checkTargetCompatibility;
- }
+ static boolean isAnnotationTargetAllowed(Annotation annotation, BlockScope scope, TypeBinding annotationType, int kind) {
+ long metaTagBits = annotationType.getAnnotationTagBits(); // could be forward reference
+ if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) {
+ // does not specify any target restriction - all locations supported in Java 7 and before are possible
+ if (kind == Binding.TYPE_PARAMETER || kind == Binding.TYPE_USE) {
+ scope.problemReporter().explitAnnotationTargetRequired(annotation);
+ }
+ return true;
+ }
- // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391201
- if ((metaTagBits & TagBits.SE7AnnotationTargetMASK) == 0
- && (metaTagBits & (TagBits.AnnotationForTypeUse | TagBits.AnnotationForTypeParameter)) != 0) {
- if (scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_8) {
- switch (kind) {
- case Binding.PACKAGE :
- case Binding.TYPE :
- case Binding.GENERIC_TYPE :
- case Binding.METHOD :
- case Binding.FIELD :
- case Binding.LOCAL :
- scope.problemReporter().invalidUsageOfTypeAnnotations(this);
- }
- }
- }
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391201
+ if ((metaTagBits & TagBits.SE7AnnotationTargetMASK) == 0
+ && (metaTagBits & (TagBits.AnnotationForTypeUse | TagBits.AnnotationForTypeParameter)) != 0) {
+ if (scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_8) {
switch (kind) {
case Binding.PACKAGE :
- if ((metaTagBits & TagBits.AnnotationForPackage) != 0)
- break checkTargetCompatibility;
- break;
- case Binding.TYPE_USE :
- if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) {
- // jsr 308
- break checkTargetCompatibility;
- }
- break;
case Binding.TYPE :
case Binding.GENERIC_TYPE :
- if (((ReferenceBinding)this.recipient).isAnnotationType()) {
- if ((metaTagBits & (TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType)) != 0)
- break checkTargetCompatibility;
- } else if ((metaTagBits & (TagBits.AnnotationForType | TagBits.AnnotationForTypeUse)) != 0) {
- break checkTargetCompatibility;
- } else if ((metaTagBits & TagBits.AnnotationForPackage) != 0) {
- if (CharOperation.equals(((ReferenceBinding)this.recipient).sourceName, TypeConstants.PACKAGE_INFO_NAME))
- break checkTargetCompatibility;
- }
-//{ObjectTeams: allow @Override for roles:
- if ( (((ReferenceBinding)this.recipient).isRole())
- && (tagBits & TagBits.AnnotationOverride) != 0)
- break checkTargetCompatibility;
-// SH}
- break;
case Binding.METHOD :
- MethodBinding methodBinding = (MethodBinding) this.recipient;
- if (methodBinding.isConstructor()) {
- if ((metaTagBits & (TagBits.AnnotationForConstructor | TagBits.AnnotationForTypeUse)) != 0)
- break checkTargetCompatibility;
- } else if ((metaTagBits & TagBits.AnnotationForMethod) != 0) {
- break checkTargetCompatibility;
- } else if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) {
- SourceTypeBinding sourceType = (SourceTypeBinding) methodBinding.declaringClass;
- MethodDeclaration methodDecl = (MethodDeclaration) sourceType.scope.referenceContext.declarationOf(methodBinding);
- if (isTypeUseCompatible(methodDecl.returnType, scope)) {
- break checkTargetCompatibility;
- }
- }
- break;
-//{ObjectTeams: method mappings
- // TODO(SH): should annotations for method mappings be controlled separately?
- case Binding.BINDING :
- if ((metaTagBits & TagBits.AnnotationForMethod) != 0)
- break checkTargetCompatibility;
- break;
-// SH}
case Binding.FIELD :
- if ((metaTagBits & TagBits.AnnotationForField) != 0) {
- break checkTargetCompatibility;
- } else if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) {
- FieldBinding sourceField = (FieldBinding) this.recipient;
- SourceTypeBinding sourceType = (SourceTypeBinding) sourceField.declaringClass;
- FieldDeclaration fieldDeclaration = sourceType.scope.referenceContext.declarationOf(sourceField);
- if (isTypeUseCompatible(fieldDeclaration.type, scope)) {
- break checkTargetCompatibility;
- }
- }
- break;
case Binding.LOCAL :
- LocalVariableBinding localVariableBinding = (LocalVariableBinding)this.recipient;
- if ((localVariableBinding.tagBits & TagBits.IsArgument) != 0) {
- if ((metaTagBits & TagBits.AnnotationForParameter) != 0) {
- break checkTargetCompatibility;
- } else if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) {
- if (isTypeUseCompatible(localVariableBinding.declaration.type, scope)) {
- break checkTargetCompatibility;
- }
- }
- } else if ((annotationType.tagBits & TagBits.AnnotationForLocalVariable) != 0) {
- break checkTargetCompatibility;
- } else if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) {
- if (isTypeUseCompatible(localVariableBinding.declaration.type, scope)) {
- break checkTargetCompatibility;
- }
- }
- break;
- case Binding.TYPE_PARAMETER : // jsr308
- // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391196
- if ((metaTagBits & (TagBits.AnnotationForTypeParameter | TagBits.AnnotationForTypeUse)) != 0) {
- break checkTargetCompatibility;
+ scope.problemReporter().invalidUsageOfTypeAnnotations(annotation);
+ }
+ }
+ }
+ switch (kind) {
+ case Binding.PACKAGE :
+ if ((metaTagBits & TagBits.AnnotationForPackage) != 0)
+ return true;
+ break;
+ case Binding.TYPE_USE :
+ if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) {
+ // jsr 308
+ return true;
+ }
+ break;
+ case Binding.TYPE :
+ case Binding.GENERIC_TYPE :
+ if (((ReferenceBinding)annotation.recipient).isAnnotationType()) {
+ if ((metaTagBits & (TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType)) != 0)
+ return true;
+ } else if ((metaTagBits & (TagBits.AnnotationForType | TagBits.AnnotationForTypeUse)) != 0) {
+ return true;
+ } else if ((metaTagBits & TagBits.AnnotationForPackage) != 0) {
+ if (CharOperation.equals(((ReferenceBinding) annotation.recipient).sourceName, TypeConstants.PACKAGE_INFO_NAME))
+ return true;
+ }
+//{ObjectTeams: allow @Override for roles:
+ if ( (((ReferenceBinding)annotation.recipient).isRole())
+ && (annotation.resolvedType.id == TypeIds.T_JavaLangObject))
+ return true;
+//SH}
+ break;
+//{ObjectTeams: method mappings
+ // TODO(SH): should annotations for method mappings be controlled separately?
+ case Binding.BINDING :
+ if ((metaTagBits & TagBits.AnnotationForMethod) != 0)
+ return true;
+ break;
+//SH}
+ case Binding.METHOD :
+ MethodBinding methodBinding = (MethodBinding) annotation.recipient;
+ if (methodBinding.isConstructor()) {
+ if ((metaTagBits & (TagBits.AnnotationForConstructor | TagBits.AnnotationForTypeUse)) != 0)
+ return true;
+ } else if ((metaTagBits & TagBits.AnnotationForMethod) != 0) {
+ return true;
+ } else if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) {
+ SourceTypeBinding sourceType = (SourceTypeBinding) methodBinding.declaringClass;
+ MethodDeclaration methodDecl = (MethodDeclaration) sourceType.scope.referenceContext.declarationOf(methodBinding);
+ if (isTypeUseCompatible(methodDecl.returnType, scope)) {
+ return true;
+ }
+ }
+ break;
+ case Binding.FIELD :
+ if ((metaTagBits & TagBits.AnnotationForField) != 0) {
+ return true;
+ } else if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) {
+ FieldBinding sourceField = (FieldBinding) annotation.recipient;
+ SourceTypeBinding sourceType = (SourceTypeBinding) sourceField.declaringClass;
+ FieldDeclaration fieldDeclaration = sourceType.scope.referenceContext.declarationOf(sourceField);
+ if (isTypeUseCompatible(fieldDeclaration.type, scope)) {
+ return true;
+ }
+ }
+ break;
+ case Binding.LOCAL :
+ LocalVariableBinding localVariableBinding = (LocalVariableBinding) annotation.recipient;
+ if ((localVariableBinding.tagBits & TagBits.IsArgument) != 0) {
+ if ((metaTagBits & TagBits.AnnotationForParameter) != 0) {
+ return true;
+ } else if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) {
+ if (isTypeUseCompatible(localVariableBinding.declaration.type, scope)) {
+ return true;
}
}
- scope.problemReporter().disallowedTargetForAnnotation(this);
- }
+ } else if ((annotationType.tagBits & TagBits.AnnotationForLocalVariable) != 0) {
+ return true;
+ } else if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) {
+ if (isTypeUseCompatible(localVariableBinding.declaration.type, scope)) {
+ return true;
+ }
+ }
+ break;
+ case Binding.TYPE_PARAMETER : // jsr308
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391196
+ if ((metaTagBits & (TagBits.AnnotationForTypeParameter | TagBits.AnnotationForTypeUse)) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static void checkAnnotationTarget(Annotation annotation, BlockScope scope, ReferenceBinding annotationType, int kind) {
+ // check (meta)target compatibility
+ if (!annotationType.isValidBinding()) {
+ // no need to check annotation usage if missing
+ return;
+ }
+ if (! isAnnotationTargetAllowed(annotation, scope, annotationType, kind)) {
+ scope.problemReporter().disallowedTargetForAnnotation(annotation);
}
- return this.resolvedType;
}
+
+ // Check and answer if an attempt to annotate a package is being made. Error should be reported by caller.
public static boolean isTypeUseCompatible(TypeReference reference, Scope scope) {
if (reference != null && !(reference instanceof SingleTypeReference)) {
Binding binding = scope.getPackage(reference.getTypeName());
@@ -1175,6 +1010,34 @@ public abstract class Annotation extends Expression {
}
return true;
}
+
+ // Complain if an attempt to annotate the enclosing type of a static member type is being made.
+ public static void isTypeUseCompatible(TypeReference reference, Scope scope, Annotation[] annotations) {
+ if (annotations == null || reference == null || reference.getAnnotatableLevels() == 1)
+ return;
+ if (scope.environment().globalOptions.sourceLevel < ClassFileConstants.JDK1_8)
+ return;
+
+ TypeBinding resolvedType = reference.resolvedType == null ? null : reference.resolvedType.leafComponentType();
+ if (resolvedType == null || !resolvedType.isNestedType())
+ return;
+
+ nextAnnotation:
+ for (int i = 0, annotationsLength = annotations.length; i < annotationsLength; i++) {
+ Annotation annotation = annotations[i];
+ long metaTagBits = annotation.resolvedType.getAnnotationTagBits();
+ if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0 && (metaTagBits & TagBits.SE7AnnotationTargetMASK) == 0) {
+ ReferenceBinding currentType = (ReferenceBinding) resolvedType;
+ while (currentType.isNestedType()) {
+ if (currentType.isStatic()) {
+ QualifiedTypeReference.rejectAnnotationsOnStaticMemberQualififer(scope, currentType, new Annotation [] { annotation });
+ continue nextAnnotation;
+ }
+ currentType = currentType.enclosingType();
+ }
+ }
+ }
+ }
public abstract void traverse(ASTVisitor visitor, BlockScope scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
index f71cf7c2f..88c513ca9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Argument.java
@@ -16,6 +16,7 @@
* Stephan Herrmann - Contributions for
* bug 186342 - [compiler][null] Using annotations for null checking
* bug 365519 - editorial cleanup after bug 186342 and bug 365387
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 409246 - [1.8][compiler] Type annotations on catch parameters not handled properly
*******************************************************************************/
@@ -93,7 +94,12 @@ public class Argument extends LocalDeclaration {
}
}
}
- resolveAnnotations(scope, this.annotations, this.binding, true);
+ if ((this.binding.tagBits & TagBits.AnnotationResolved) == 0) {
+ resolveAnnotations(scope, this.annotations, this.binding, true);
+ Annotation.isTypeUseCompatible(this.type, scope, this.annotations);
+ if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8)
+ scope.validateNullAnnotation(this.binding.tagBits, this.type, this.annotations);
+ }
this.binding.declaration = this;
return this.binding.type; // might have been updated during resolveAnnotations (for typeAnnotations)
}
@@ -235,49 +241,7 @@ public class Argument extends LocalDeclaration {
this.binding = new CatchParameterBinding(this, exceptionType, this.modifiers, false); // argument decl, but local var (where isArgument = false)
}
resolveAnnotations(scope, this.annotations, this.binding, true);
-
- // Type annotations may need attaching to the type references
- // Example of code this block handles: } catch(@A Exception e) {
- if (this.annotations != null) {
- for (int i = 0, max = this.annotations.length; i < max; i++) {
- Annotation annotation = this.annotations[i];
- if ((annotation.resolvedType.tagBits & (TagBits.AnnotationForTypeParameter | TagBits.AnnotationForTypeUse)) != 0) {
- // Copy it to the type reference.
- if (this.type instanceof UnionTypeReference) {
- // Only need to consider the first element of the union type reference
- TypeReference firstTypeReference = ((UnionTypeReference) this.type).typeReferences[0];
- Annotation[][] annotationsOnFirstReference = firstTypeReference.annotations;
- if (annotationsOnFirstReference == null) {
- firstTypeReference.annotations = annotationsOnFirstReference = new Annotation[firstTypeReference.getAnnotatableLevels()][];
- }
- if (annotationsOnFirstReference[0] == null) {
- firstTypeReference.annotations[0] = new Annotation[] { annotation };
- } else {
- int len = annotationsOnFirstReference.length;
- Annotation[] newAnnotations = new Annotation[len + 1];
- System.arraycopy(annotationsOnFirstReference[0], 0, newAnnotations, 0, len);
- newAnnotations[len] = annotation;
- firstTypeReference.annotations[0] = newAnnotations;
- }
- firstTypeReference.bits |= ASTNode.HasTypeAnnotations;
- } else {
- if (this.type.annotations == null) {
- this.type.annotations = new Annotation[this.type.getAnnotatableLevels()][];
- }
- if (this.type.annotations[0] == null) {
- this.type.annotations[0] = new Annotation[] { annotation };
- } else {
- int len = this.type.annotations[0].length;
- Annotation[] newAnnotations = new Annotation[len + 1];
- System.arraycopy(this.type.annotations[0], 0, newAnnotations, 0, len);
- newAnnotations[len] = annotation;
- this.type.annotations[0] = newAnnotations;
- }
- this.type.bits |= ASTNode.HasTypeAnnotations;
- }
- }
- }
- }
+ Annotation.isTypeUseCompatible(this.type, scope, this.annotations);
scope.addLocalVariable(this.binding);
this.binding.setConstant(Constant.NotAConstant);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
index 172f5a3e3..55b07c3e8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayAllocationExpression.java
@@ -17,14 +17,18 @@
* bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
* bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking
+ * Bug 417758 - [1.8][null] Null safety compromise during array creation.
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
* Bug 409247 - [1.8][compiler] Verify error with code allocating multidimensional array
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+import java.util.List;
+
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.impl.*;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationCollector;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -71,7 +75,7 @@ public class ArrayAllocationExpression extends Expression {
int pc = codeStream.position;
if (this.initializer != null) {
- this.initializer.generateCode(this.type, this.annotationsOnDimensions, currentScope, codeStream, valueRequired);
+ this.initializer.generateCode(this.type, this, currentScope, codeStream, valueRequired);
return;
}
@@ -86,10 +90,10 @@ public class ArrayAllocationExpression extends Expression {
// array allocation
if (explicitDimCount == 1) {
// Mono-dimensional array
- codeStream.newArray(this.type, this.annotationsOnDimensions, (ArrayBinding)this.resolvedType);
+ codeStream.newArray(this.type, this, (ArrayBinding)this.resolvedType);
} else {
// Multi-dimensional array
- codeStream.multianewarray(this.type, this.resolvedType, explicitDimCount, this.dimensions.length, this.annotationsOnDimensions);
+ codeStream.multianewarray(this.type, this.resolvedType, explicitDimCount, this);
}
if (valueRequired) {
codeStream.generateImplicitConversion(this.implicitConversion);
@@ -183,6 +187,10 @@ public class ArrayAllocationExpression extends Expression {
// SH}
this.resolvedType = scope.createArrayType(referenceType, this.dimensions.length);
+ if (this.annotationsOnDimensions != null) {
+ this.resolvedType = resolveAnnotations(scope, this.annotationsOnDimensions, this.resolvedType);
+ }
+
// check the initializer
if (this.initializer != null) {
if ((this.initializer.resolveTypeExpecting(scope, this.resolvedType)) != null)
@@ -192,9 +200,6 @@ public class ArrayAllocationExpression extends Expression {
return null;
}
}
- if (this.annotationsOnDimensions != null) {
- this.resolvedType = resolveAnnotations(scope, this.annotationsOnDimensions, this.resolvedType);
- }
return this.resolvedType;
}
@@ -204,6 +209,11 @@ public class ArrayAllocationExpression extends Expression {
int dimensionsLength = this.dimensions.length;
this.type.traverse(visitor, scope);
for (int i = 0; i < dimensionsLength; i++) {
+ Annotation [] annotations = this.annotationsOnDimensions == null ? null : this.annotationsOnDimensions[i];
+ int annotationsLength = annotations == null ? 0 : annotations.length;
+ for (int j = 0; j < annotationsLength; j++) {
+ annotations[j].traverse(visitor, scope);
+ }
if (this.dimensions[i] != null)
this.dimensions[i].traverse(visitor, scope);
}
@@ -212,4 +222,23 @@ public class ArrayAllocationExpression extends Expression {
}
visitor.endVisit(this, scope);
}
+
+ public void getAllAnnotationContexts(int targetType, int info, List allTypeAnnotationContexts) {
+ AnnotationCollector collector = new AnnotationCollector(this, targetType, info, allTypeAnnotationContexts);
+ this.type.traverse(collector, (BlockScope) null);
+ if (this.annotationsOnDimensions != null) {
+ int dimensionsLength = this.dimensions.length;
+ for (int i = 0; i < dimensionsLength; i++) {
+ Annotation [] annotations = this.annotationsOnDimensions[i];
+ int annotationsLength = annotations == null ? 0 : annotations.length;
+ for (int j = 0; j < annotationsLength; j++) {
+ annotations[j].traverse(collector, (BlockScope) null);
+ }
+ }
+ }
+ }
+
+ public Annotation[][] getAnnotationsOnDimensions() {
+ return this.annotationsOnDimensions;
+ }
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
index d39eeef47..caa6e5bac 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayInitializer.java
@@ -15,14 +15,17 @@
* bug 368546 - [compiler][resource] Avoid remaining false positives found when compiling the Eclipse SDK
* bug 370639 - [compiler][resource] restore the default for resource leak warnings
* bug 388996 - [compiler][resource] Incorrect 'potential resource leak'
+ * Bug 417758 - [1.8][null] Null safety compromise during array creation.
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.*;
@@ -42,13 +45,19 @@ public class ArrayInitializer extends Expression {
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
if (this.expressions != null) {
- boolean analyseResources = currentScope.compilerOptions().analyseResourceLeaks;
+ CompilerOptions compilerOptions = currentScope.compilerOptions();
+ boolean analyseResources = compilerOptions.analyseResourceLeaks;
+ boolean evalNullTypeAnnotations = compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8
+ && compilerOptions.isAnnotationBasedNullAnalysisEnabled;
for (int i = 0, max = this.expressions.length; i < max; i++) {
flowInfo = this.expressions[i].analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
if (analyseResources && FakedTrackingVariable.isAnyCloseable(this.expressions[i].resolvedType)) {
flowInfo = FakedTrackingVariable.markPassedToOutside(currentScope, this.expressions[i], flowInfo, flowContext, false);
}
+ if (evalNullTypeAnnotations) {
+ checkAgainstNullTypeAnnotation(currentScope, this.binding.elementsType(), this.expressions[i], flowContext, flowInfo);
+ }
}
}
return flowInfo;
@@ -61,13 +70,13 @@ public class ArrayInitializer extends Expression {
/**
* Code generation for a array initializer
*/
- public void generateCode(TypeReference typeReference, Annotation[][] annotationsOnDimensions, BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+ public void generateCode(TypeReference typeReference, ArrayAllocationExpression allocationExpression, BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
// Flatten the values and compute the dimensions, by iterating in depth into nested array initializers
int pc = codeStream.position;
int expressionLength = (this.expressions == null) ? 0: this.expressions.length;
codeStream.generateInlinedValue(expressionLength);
- codeStream.newArray(typeReference, annotationsOnDimensions, this.binding);
+ codeStream.newArray(typeReference, allocationExpression, this.binding);
if (this.expressions != null) {
// binding is an ArrayType, so I can just deal with the dimension
int elementsTypeID = this.binding.dimensions > 1 ? -1 : this.binding.leafComponentType.id;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
index ade9f79c1..63eb10e90 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayQualifiedTypeReference.java
@@ -22,7 +22,8 @@ import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
public class ArrayQualifiedTypeReference extends QualifiedTypeReference {
int dimensions;
- Annotation[][] annotationsOnDimensions; // jsr308 style type annotations on dimensions
+ private Annotation[][] annotationsOnDimensions; // jsr308 style type annotations on dimensions
+ public int extendedDimensions;
//{ObjectTeams: mark generated reference:
public ArrayQualifiedTypeReference(char[][] sources , int dim, long[] poss, boolean isGenerated) {
@@ -49,8 +50,17 @@ public class ArrayQualifiedTypeReference extends QualifiedTypeReference {
return this.dimensions;
}
- public Annotation[][] getAnnotationsOnDimensions() {
- return this.annotationsOnDimensions;
+ /**
+ @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getAnnotationsOnDimensions(boolean)
+ */
+ public Annotation[][] getAnnotationsOnDimensions(boolean useSourceOrder) {
+ if (useSourceOrder || this.annotationsOnDimensions == null || this.annotationsOnDimensions.length == 0 || this.extendedDimensions == 0 || this.extendedDimensions == this.dimensions)
+ return this.annotationsOnDimensions;
+ Annotation [][] externalAnnotations = new Annotation[this.dimensions][];
+ final int baseDimensions = this.dimensions - this.extendedDimensions;
+ System.arraycopy(this.annotationsOnDimensions, baseDimensions, externalAnnotations, 0, this.extendedDimensions);
+ System.arraycopy(this.annotationsOnDimensions, 0, externalAnnotations, this.extendedDimensions, baseDimensions);
+ return externalAnnotations;
}
public void setAnnotationsOnDimensions(Annotation [][] annotationsOnDimensions) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
index e6cd3e0ea..011600f7a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ArrayTypeReference.java
@@ -23,8 +23,9 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
public class ArrayTypeReference extends SingleTypeReference {
public int dimensions;
- public Annotation[][] annotationsOnDimensions; // jsr308 style type annotations on dimensions.
+ private Annotation[][] annotationsOnDimensions; // jsr308 style type annotations on dimensions.
public int originalSourceEnd;
+ public int extendedDimensions;
/**
* ArrayTypeReference constructor comment.
@@ -53,9 +54,19 @@ public class ArrayTypeReference extends SingleTypeReference {
return this.dimensions;
}
- public Annotation[][] getAnnotationsOnDimensions() {
- return this.annotationsOnDimensions;
+ /**
+ @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getAnnotationsOnDimensions(boolean)
+ */
+ public Annotation[][] getAnnotationsOnDimensions(boolean useSourceOrder) {
+ if (useSourceOrder || this.annotationsOnDimensions == null || this.annotationsOnDimensions.length == 0 || this.extendedDimensions == 0 || this.extendedDimensions == this.dimensions)
+ return this.annotationsOnDimensions;
+ Annotation [][] externalAnnotations = new Annotation[this.dimensions][];
+ final int baseDimensions = this.dimensions - this.extendedDimensions;
+ System.arraycopy(this.annotationsOnDimensions, baseDimensions, externalAnnotations, 0, this.extendedDimensions);
+ System.arraycopy(this.annotationsOnDimensions, 0, externalAnnotations, this.extendedDimensions, baseDimensions);
+ return externalAnnotations;
}
+
public void setAnnotationsOnDimensions(Annotation [][] annotationsOnDimensions) {
this.annotationsOnDimensions = annotationsOnDimensions;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
index 05dc8f1f3..1d09d0706 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
@@ -22,6 +22,7 @@
* bug 400761 - [compiler][null] null may be return as boolean without a diagnostic
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
* Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -516,7 +517,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
// from valueIFTrue or valueIfFalse to the receiver constant
this.constant = condConstant.booleanValue() ? trueConstant : falseConstant;
}
- if (valueIfTrueType == valueIfFalseType) { // harmed the implicit conversion
+ if (TypeBinding.equalsEquals(valueIfTrueType, valueIfFalseType)) { // harmed the implicit conversion
this.valueIfTrue.computeConversion(scope, valueIfTrueType, this.originalValueIfTrueType);
this.valueIfFalse.computeConversion(scope, valueIfFalseType, this.originalValueIfFalseType);
if (valueIfTrueType == TypeBinding.BOOLEAN) {
@@ -533,7 +534,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
: this.optimizedIfFalseConstant;
}
}
- return this.resolvedType = valueIfTrueType;
+ return this.resolvedType = NullAnnotationMatching.moreDangerousType(valueIfTrueType, valueIfFalseType);
}
// Determine the return type depending on argument types
// Numeric types
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
index 84c6eae1a..cfe58d258 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
@@ -691,7 +691,7 @@ public void maybeRecordByteCode(ClassFile classFile, int methodAttributeOffset)
// SH}
public void getAllAnnotationContexts(int targetType, List allAnnotationContexts) {
- AnnotationCollector collector = new AnnotationCollector(this, targetType, allAnnotationContexts);
+ AnnotationCollector collector = new AnnotationCollector(null, targetType, allAnnotationContexts);
for (int i = 0, max = this.annotations.length; i < max; i++) {
Annotation annotation = this.annotations[i];
annotation.traverse(collector, (BlockScope) null);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
index 990746174..2227eac83 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Expression.java
@@ -23,7 +23,8 @@
* bug 400761 - [compiler][null] null may be return as boolean without a diagnostic
* bug 402993 - [null] Follow up of bug 401088: Missing warning about redundant null check
* bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking
- * Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
+ * Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -398,7 +399,7 @@ public final boolean checkCastTypesCompatibility(
boolean use17specifics = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_7;
if (castType.isBaseType()) {
if (expressionType.isBaseType()) {
- if (expressionType == castType) {
+ if (TypeBinding.equalsEquals(expressionType, castType)) {
if (expression != null) {
this.constant = expression.constant; //use the same constant
}
@@ -453,7 +454,7 @@ public final boolean checkCastTypesCompatibility(
return false;
case Binding.ARRAY_TYPE :
- if (castType == expressionType) {
+ if (TypeBinding.equalsEquals(castType, expressionType)) {
tagAsUnnecessaryCast(scope, castType);
return true; // identity conversion
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
index 4d1682a13..617379f50 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
@@ -170,7 +170,7 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
public void getAllAnnotationContexts(int targetType, List allAnnotationContexts) {
- AnnotationCollector collector = new AnnotationCollector(this, targetType, allAnnotationContexts);
+ AnnotationCollector collector = new AnnotationCollector(this.type, targetType, allAnnotationContexts);
for (int i = 0, max = this.annotations.length; i < max; i++) {
Annotation annotation = this.annotations[i];
annotation.traverse(collector, (BlockScope) null);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
index 5acf63f53..94c2f6b18 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldReference.java
@@ -891,7 +891,7 @@ public void traverse(ASTVisitor visitor, BlockScope scope) {
public VariableBinding nullAnnotatedVariableBinding(boolean supportTypeAnnotations) {
if (this.binding != null) {
if (supportTypeAnnotations
- || ((this.binding.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) != 0)) {
+ || ((this.binding.tagBits & TagBits.AnnotationNullMASK) != 0)) {
return this.binding;
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java
index 4e6475292..b2e589d56 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FunctionalExpression.java
@@ -38,7 +38,8 @@ public abstract class FunctionalExpression extends Expression {
TypeBinding expectedType;
public MethodBinding descriptor;
- public MethodBinding binding;
+ public MethodBinding binding; // Code generation binding. May include synthetics. See getMethodBinding()
+ protected MethodBinding actualMethodBinding; // void of synthetics.
boolean ignoreFurtherInvestigation;
protected ExpressionContext expressionContext = VANILLA_CONTEXT;
protected SimpleLookupTable resultExpressions;
@@ -51,7 +52,10 @@ public abstract class FunctionalExpression extends Expression {
public FunctionalExpression(CompilationResult compilationResult) {
this.compilationResult = compilationResult;
}
-
+ // Return the actual (non-code generation) method binding that is void of synthetics.
+ public MethodBinding getMethodBinding() {
+ return null;
+ }
public void setExpectedType(TypeBinding expectedType) {
this.expectedType = this.ellipsisArgument ? ((ArrayBinding) expectedType).elementsType() : expectedType;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
index 55c205c50..d8a595c65 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
@@ -18,6 +18,7 @@
* Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
* Bug 416307 - [1.8][compiler][null] subclass with type parameter substitution confuses null checking
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Andy Clement - Contributions for
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
*******************************************************************************/
@@ -156,7 +157,6 @@ public TypeBinding resolveType(BlockScope scope) {
TypeBinding checkedType = this.type.resolveType(scope, true /* check bounds*/);
if (expressionType != null && checkedType != null && NullAnnotationMatching.analyse(checkedType, expressionType, -1).isAnyMismatch()) {
scope.problemReporter().nullAnnotationUnsupportedLocation(this.type);
- checkedType = checkedType.unannotated();
}
if (expressionType == null || checkedType == null)
return null;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntersectionCastTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntersectionCastTypeReference.java
index 27da4692c..fc51a505a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntersectionCastTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/IntersectionCastTypeReference.java
@@ -40,11 +40,7 @@ public class IntersectionCastTypeReference extends TypeReference {
}
}
- public TypeReference copyDims(int dim) {
- throw new UnsupportedOperationException(); // no syntax for this.
- }
-
- public TypeReference copyDims(int dim, Annotation[][] annotationsOnDimensions) {
+ public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) {
throw new UnsupportedOperationException(); // no syntax for this.
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocImplicitTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocImplicitTypeReference.java
index 7f985aa6e..cfb139c3c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocImplicitTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocImplicitTypeReference.java
@@ -28,14 +28,8 @@ public class JavadocImplicitTypeReference extends TypeReference {
this.sourceStart = pos;
this.sourceEnd = pos;
}
- /* (non-Javadoc)
- * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#copyDims(int)
- */
- public TypeReference copyDims(int dim) {
- return null;
- }
- public TypeReference copyDims(int dim, Annotation[][] annotationsOnDimensions) {
+ public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) {
return null;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
index 8c2609425..ea454757a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java
@@ -49,6 +49,7 @@ import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
+import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
@@ -789,6 +790,17 @@ public class LambdaExpression extends FunctionalExpression implements ReferenceC
return this.outerLocalVariables[i];
return null;
}
+
+ // Return the actual method binding devoid of synthetics.
+ public MethodBinding getMethodBinding() {
+ if (this.actualMethodBinding == null) {
+ this.actualMethodBinding = new MethodBinding(this.binding.modifiers, this.binding.selector, this.binding.returnType,
+ this.binding instanceof SyntheticMethodBinding ? this.descriptor.parameters : this.binding.parameters, // retain any faults in parameter list.
+ this.binding.thrownExceptions, this.binding.declaringClass);
+ this.actualMethodBinding.tagBits = this.binding.tagBits;
+ }
+ return this.actualMethodBinding;
+ }
}
class IncongruentLambdaException extends RuntimeException {
private static final long serialVersionUID = 4145723509219836114L;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
index d80efc2aa..b233bdbce 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/LocalDeclaration.java
@@ -370,6 +370,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
}
// only resolve annotation at the end, for constant to be positioned before (96991)
resolveAnnotations(scope, this.annotations, this.binding, true);
+ Annotation.isTypeUseCompatible(this.type, scope, this.annotations);
if (!scope.validateNullAnnotation(this.binding.tagBits, this.type, this.annotations))
this.binding.tagBits &= ~TagBits.AnnotationNullMASK;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
index 8a20f1c0d..bf1905cf6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
@@ -39,7 +39,7 @@
* Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099
* Bug 405569 - Resource leak check false positive when using DbUtils.closeQuietly
* Bug 411964 - [1.8][null] leverage null type annotation in foreach statement
- * Bug 405569 - Resource leak check false positive when using DbUtils.closeQuietly
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Jesper S Moller - Contributions for
* Bug 378674 - "The method can be declared as static" is wrong
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
@@ -214,7 +214,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
if (nonStatic) {
this.receiver.checkNPE(currentScope, flowContext, flowInfo);
- }
+ }
if (this.arguments != null) {
int length = this.arguments.length;
@@ -235,7 +235,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
flowInfo = analyseNullAssertion(currentScope, argument, flowContext, flowInfo, true);
break;
default:
- flowInfo = argument.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+ flowInfo = argument.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
}
if (analyseResources) {
// if argument is an AutoCloseable insert info that it *may* be closed (by the target method, i.e.)
@@ -244,13 +244,6 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
}
analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
}
- if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8) {
- if (this.binding instanceof ParameterizedGenericMethodBinding && this.typeArguments != null) {
- TypeVariableBinding[] typeVariables = this.binding.original().typeVariables();
- for (int i = 0; i < this.typeArguments.length; i++)
- this.typeArguments[i].checkNullConstraints(currentScope, typeVariables, i);
- }
- }
ReferenceBinding[] thrownExceptions;
if ((thrownExceptions = this.binding.thrownExceptions) != Binding.NO_EXCEPTIONS) {
if ((this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null) {
@@ -1114,12 +1107,21 @@ public TypeBinding resolveType(BlockScope scope) {
return null;
}
- if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) {
- // not interested in reporting problems against this.binding:
+ if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) {
+ if ((this.binding.tagBits & TagBits.IsNullnessKnown) == 0) {
+ // not interested in reporting problems against this.binding:
//{ObjectTeams: added 2nd arg:
- new ImplicitNullAnnotationVerifier(compilerOptions.inheritNullAnnotations, scope.environment())
+ new ImplicitNullAnnotationVerifier(compilerOptions.inheritNullAnnotations, scope.environment())
// SH}
- .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope);
+ .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope);
+ }
+ if (compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8) {
+ if (this.binding instanceof ParameterizedGenericMethodBinding && this.typeArguments != null) {
+ TypeVariableBinding[] typeVariables = this.binding.original().typeVariables();
+ for (int i = 0; i < this.typeArguments.length; i++)
+ this.typeArguments[i].checkNullConstraints(scope, typeVariables, i);
+ }
+ }
}
if (((this.bits & ASTNode.InsideExpressionStatement) != 0)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
index 73077e746..d287ba521 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
@@ -239,7 +239,7 @@ public class MethodDeclaration extends AbstractMethodDeclaration {
// SH}
public void getAllAnnotationContexts(int targetType, List allAnnotationContexts) {
- AnnotationCollector collector = new AnnotationCollector(this, targetType, allAnnotationContexts);
+ AnnotationCollector collector = new AnnotationCollector(this.returnType, targetType, allAnnotationContexts);
for (int i = 0, max = this.annotations.length; i < max; i++) {
Annotation annotation = this.annotations[i];
annotation.traverse(collector, (BlockScope) null);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java
index 24a94937c..009cb5f89 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/NullAnnotationMatching.java
@@ -106,8 +106,8 @@ public class NullAnnotationMatching {
severity = 1; // required is annotated, provided not, need unchecked conversion
} else {
for (int i=0; i<=dims; i++) {
- long requiredBits = requiredDimsTagBits[i] & TagBits.AnnotationNullMASK;
- long providedBits = providedDimsTagBits[i] & TagBits.AnnotationNullMASK;
+ long requiredBits = validNullTagBits(requiredDimsTagBits[i]);
+ long providedBits = validNullTagBits(providedDimsTagBits[i]);
if (i > 0)
nullStatus = -1; // don't use beyond the outermost dimension
severity = Math.max(severity, computeNullProblemSeverity(requiredBits, providedBits, nullStatus));
@@ -121,11 +121,11 @@ public class NullAnnotationMatching {
}
}
} else if (requiredType.hasNullTypeAnnotations() || providedType.hasNullTypeAnnotations()) {
- long requiredBits = requiredType.tagBits & TagBits.AnnotationNullMASK;
+ long requiredBits = validNullTagBits(requiredType.tagBits);
if (requiredBits != TagBits.AnnotationNullable // nullable lhs accepts everything, ...
|| nullStatus == -1) // only at detail/recursion even nullable must be matched exactly
{
- long providedBits = providedType.tagBits & TagBits.AnnotationNullMASK;
+ long providedBits = validNullTagBits(providedType.tagBits);
severity = computeNullProblemSeverity(requiredBits, providedBits, nullStatus);
}
if (severity < 2) {
@@ -144,8 +144,12 @@ public class NullAnnotationMatching {
}
}
} else if (requiredType instanceof WildcardBinding) {
- NullAnnotationMatching status = analyse(((WildcardBinding) requiredType).bound, providedType, nullStatus);
- severity = Math.max(severity, status.severity);
+ WildcardBinding wildcardBinding = (WildcardBinding) requiredType;
+ if (wildcardBinding.bound != null) {
+ NullAnnotationMatching status = analyse(wildcardBinding.bound, providedType, nullStatus);
+ severity = Math.max(severity, status.severity);
+ }
+ // TODO(stephan): what about otherBounds? Do we accept "? extends @NonNull I1 & @Nullable I2" in the first place??
}
TypeBinding requiredEnclosing = requiredType.enclosingType();
TypeBinding providedEnclosing = providedType.enclosingType();
@@ -160,14 +164,40 @@ public class NullAnnotationMatching {
return new NullAnnotationMatching(severity, superTypeHint);
}
+ public static long validNullTagBits(long bits) {
+ bits &= TagBits.AnnotationNullMASK;
+ return bits == TagBits.AnnotationNullMASK ? 0 : bits;
+ }
+
+ /** Provided that both types are {@link TypeBinding#equalsEquals}, return the one that is more likely to show null at runtime. */
+ public static TypeBinding moreDangerousType(TypeBinding one, TypeBinding two) {
+ if (one == null) return null;
+ long oneNullBits = validNullTagBits(one.tagBits);
+ long twoNullBits = validNullTagBits(two.tagBits);
+ if (oneNullBits != twoNullBits) {
+ if (oneNullBits == TagBits.AnnotationNullable)
+ return one; // nullable is dangerous
+ if (twoNullBits == TagBits.AnnotationNullable)
+ return two; // nullable is dangerous
+ // below this point we have unknown vs. nonnull, which is which?
+ if (oneNullBits == 0)
+ return one; // unknown is more dangerous than nonnull
+ return two; // unknown is more dangerous than nonnull
+ } else if (one != two) {
+ if (analyse(one, two, -1).isAnyMismatch())
+ return two; // two doesn't snugly fit into one, so it must be more dangerous
+ }
+ return one;
+ }
+
private static int computeNullProblemSeverity(long requiredBits, long providedBits, int nullStatus) {
if (requiredBits != 0 && requiredBits != providedBits) {
+ if (requiredBits == TagBits.AnnotationNonNull && nullStatus == FlowInfo.NON_NULL) {
+ return 0; // OK by flow analysis
+ }
if (providedBits != 0) {
return 2; // mismatching annotations
} else {
- if (requiredBits == TagBits.AnnotationNonNull && nullStatus == FlowInfo.NON_NULL) {
- return 0; // OK by flow analysis
- }
return 1; // need unchecked conversion regarding type detail
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
index 17cd958f9..d280a3669 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedQualifiedTypeReference.java
@@ -76,7 +76,7 @@ public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeRefer
}
public ParameterizedQualifiedTypeReference(char[][] tokens, TypeReference[][] typeArguments, int dim, Annotation[][] annotationsOnDimensions, long[] positions) {
this(tokens, typeArguments, dim, positions);
- this.annotationsOnDimensions = annotationsOnDimensions;
+ setAnnotationsOnDimensions(annotationsOnDimensions);
if (annotationsOnDimensions != null) {
this.bits |= ASTNode.HasTypeAnnotations;
}
@@ -103,16 +103,15 @@ public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeRefer
}
}
}
- public TypeReference copyDims(int dim){
- return new ParameterizedQualifiedTypeReference(this.tokens, this.typeArguments, dim, this.sourcePositions);
- }
- public TypeReference copyDims(int dim, Annotation[][] dimensionAnnotations){
- ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference = new ParameterizedQualifiedTypeReference(this.tokens, this.typeArguments, dim, dimensionAnnotations, this.sourcePositions);
- parameterizedQualifiedTypeReference.bits |= (this.bits & ASTNode.HasTypeAnnotations);
- if (dimensionAnnotations != null) {
- parameterizedQualifiedTypeReference.bits |= ASTNode.HasTypeAnnotations;
- }
- return parameterizedQualifiedTypeReference;
+ public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) {
+ int totalDimensions = this.dimensions() + additionalDimensions;
+ Annotation [][] allAnnotations = getMergedAnnotationsOnDimensions(additionalDimensions, additionalAnnotations);
+ ParameterizedQualifiedTypeReference pqtr = new ParameterizedQualifiedTypeReference(this.tokens, this.typeArguments, totalDimensions, allAnnotations, this.sourcePositions);
+ pqtr.annotations = this.annotations;
+ pqtr.bits |= (this.bits & ASTNode.HasTypeAnnotations);
+ if (!isVarargs)
+ pqtr.extendedDimensions = additionalDimensions;
+ return pqtr;
}
public boolean isParameterizedTypeReference() {
return true;
@@ -155,6 +154,10 @@ public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeRefer
return qParamName;
}
+ public TypeReference[][] getTypeArguments() {
+ return this.typeArguments;
+ }
+
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
*/
@@ -253,7 +256,8 @@ public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeRefer
: scope.environment().convertToParameterizedType(qualifyingType);
}
} else {
- rejectAnnotationsOnStaticMemberQualififer(scope, currentType, i);
+ if (this.annotations != null)
+ rejectAnnotationsOnStaticMemberQualififer(scope, currentType, this.annotations[i-1]);
if (typeIsConsistent && currentType.isStatic()
&& (qualifyingType.isParameterizedTypeWithActualArguments() || qualifyingType.isGenericType())) {
scope.problemReporter().staticMemberOfParameterizedType(this, scope.environment().createParameterizedType((ReferenceBinding)currentType.erasure(), null, qualifyingType), i);
@@ -408,26 +412,27 @@ public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeRefer
}
output.append('>');
}
+ Annotation [][] annotationsOnDimensions = this.getAnnotationsOnDimensions();
if ((this.bits & IsVarArgs) != 0) {
for (int i= 0 ; i < this.dimensions - 1; i++) {
- if (this.annotationsOnDimensions != null && this.annotationsOnDimensions[i] != null) {
+ if (annotationsOnDimensions != null && annotationsOnDimensions[i] != null) {
output.append(" "); //$NON-NLS-1$
- printAnnotations(this.annotationsOnDimensions[i], output);
+ printAnnotations(annotationsOnDimensions[i], output);
output.append(" "); //$NON-NLS-1$
}
output.append("[]"); //$NON-NLS-1$
}
- if (this.annotationsOnDimensions != null && this.annotationsOnDimensions[this.dimensions - 1] != null) {
+ if (annotationsOnDimensions != null && annotationsOnDimensions[this.dimensions - 1] != null) {
output.append(" "); //$NON-NLS-1$
- printAnnotations(this.annotationsOnDimensions[this.dimensions - 1], output);
+ printAnnotations(annotationsOnDimensions[this.dimensions - 1], output);
output.append(" "); //$NON-NLS-1$
}
output.append("..."); //$NON-NLS-1$
} else {
for (int i= 0 ; i < this.dimensions; i++) {
- if (this.annotationsOnDimensions != null && this.annotationsOnDimensions[i] != null) {
+ if (annotationsOnDimensions != null && annotationsOnDimensions[i] != null) {
output.append(" "); //$NON-NLS-1$
- printAnnotations(this.annotationsOnDimensions[i], output);
+ printAnnotations(annotationsOnDimensions[i], output);
output.append(" "); //$NON-NLS-1$
}
output.append("[]"); //$NON-NLS-1$
@@ -452,9 +457,10 @@ public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeRefer
this.annotations[i][j].traverse(visitor, scope);
}
}
- if (this.annotationsOnDimensions != null) {
- for (int i = 0, max = this.annotationsOnDimensions.length; i < max; i++) {
- Annotation[] annotations2 = this.annotationsOnDimensions[i];
+ Annotation [][] annotationsOnDimensions = getAnnotationsOnDimensions(true);
+ if (annotationsOnDimensions != null) {
+ for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) {
+ Annotation[] annotations2 = annotationsOnDimensions[i];
for (int j = 0, max2 = annotations2 == null ? 0 : annotations2.length; j < max2; j++) {
Annotation annotation = annotations2[j];
annotation.traverse(visitor, scope);
@@ -482,9 +488,10 @@ public class ParameterizedQualifiedTypeReference extends ArrayQualifiedTypeRefer
this.annotations[i][j].traverse(visitor, scope);
}
}
- if (this.annotationsOnDimensions != null) {
- for (int i = 0, max = this.annotationsOnDimensions.length; i < max; i++) {
- Annotation[] annotations2 = this.annotationsOnDimensions[i];
+ Annotation [][] annotationsOnDimensions = getAnnotationsOnDimensions(true);
+ if (annotationsOnDimensions != null) {
+ for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) {
+ Annotation[] annotations2 = annotationsOnDimensions[i];
for (int j = 0, max2 = annotations2 == null ? 0 : annotations2.length; j < max2; j++) {
Annotation annotation = annotations2[j];
annotation.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
index e33a10a1c..eff0e7ccf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ParameterizedSingleTypeReference.java
@@ -78,7 +78,7 @@ public class ParameterizedSingleTypeReference extends ArrayTypeReference {
}
public ParameterizedSingleTypeReference(char[] name, TypeReference[] typeArguments, int dim, Annotation[][] annotationsOnDimensions, long pos) {
this(name, typeArguments, dim, pos);
- this.annotationsOnDimensions = annotationsOnDimensions;
+ setAnnotationsOnDimensions(annotationsOnDimensions);
if (annotationsOnDimensions != null) {
this.bits |= ASTNode.HasTypeAnnotations;
}
@@ -96,18 +96,15 @@ public class ParameterizedSingleTypeReference extends ArrayTypeReference {
}
}
}
- /**
- * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#copyDims(int)
- */
- public TypeReference copyDims(int dim) {
- return new ParameterizedSingleTypeReference(this.token, this.typeArguments, dim, (((long)this.sourceStart)<<32)+this.sourceEnd);
- }
- public TypeReference copyDims(int dim, Annotation [][] annotationsOnDims) {
- ParameterizedSingleTypeReference parameterizedSingleTypeReference = new ParameterizedSingleTypeReference(this.token, this.typeArguments, dim, annotationsOnDims, (((long)this.sourceStart)<<32)+this.sourceEnd);
+
+ public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation [][] additionalAnnotations, boolean isVarargs) {
+ int totalDimensions = this.dimensions() + additionalDimensions;
+ Annotation [][] allAnnotations = getMergedAnnotationsOnDimensions(additionalDimensions, additionalAnnotations);
+ ParameterizedSingleTypeReference parameterizedSingleTypeReference = new ParameterizedSingleTypeReference(this.token, this.typeArguments, totalDimensions, allAnnotations, (((long) this.sourceStart) << 32) + this.sourceEnd);
+ parameterizedSingleTypeReference.annotations = this.annotations;
parameterizedSingleTypeReference.bits |= (this.bits & ASTNode.HasTypeAnnotations);
- if (annotationsOnDims != null) {
- parameterizedSingleTypeReference.bits |= ASTNode.HasTypeAnnotations;
- }
+ if (!isVarargs)
+ parameterizedSingleTypeReference.extendedDimensions = additionalDimensions;
return parameterizedSingleTypeReference;
}
@@ -152,6 +149,11 @@ public class ParameterizedSingleTypeReference extends ArrayTypeReference {
}
return new char[][]{ name };
}
+
+ public TypeReference[][] getTypeArguments() {
+ return new TypeReference[][] { this.typeArguments };
+ }
+
/**
* @see org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
*/
@@ -494,26 +496,27 @@ public class ParameterizedSingleTypeReference extends ArrayTypeReference {
this.typeArguments[max].print(0, output);
}
output.append(">"); //$NON-NLS-1$
+ Annotation [][] annotationsOnDimensions = getAnnotationsOnDimensions();
if ((this.bits & IsVarArgs) != 0) {
for (int i= 0 ; i < this.dimensions - 1; i++) {
- if (this.annotationsOnDimensions != null && this.annotationsOnDimensions[i] != null) {
+ if (annotationsOnDimensions != null && annotationsOnDimensions[i] != null) {
output.append(" "); //$NON-NLS-1$
- printAnnotations(this.annotationsOnDimensions[i], output);
+ printAnnotations(annotationsOnDimensions[i], output);
output.append(" "); //$NON-NLS-1$
}
output.append("[]"); //$NON-NLS-1$
}
- if (this.annotationsOnDimensions != null && this.annotationsOnDimensions[this.dimensions - 1] != null) {
+ if (annotationsOnDimensions != null && annotationsOnDimensions[this.dimensions - 1] != null) {
output.append(" "); //$NON-NLS-1$
- printAnnotations(this.annotationsOnDimensions[this.dimensions - 1], output);
+ printAnnotations(annotationsOnDimensions[this.dimensions - 1], output);
output.append(" "); //$NON-NLS-1$
}
output.append("..."); //$NON-NLS-1$
} else {
for (int i= 0 ; i < this.dimensions; i++) {
- if (this.annotationsOnDimensions != null && this.annotationsOnDimensions[i] != null) {
+ if (annotationsOnDimensions != null && annotationsOnDimensions[i] != null) {
output.append(" "); //$NON-NLS-1$
- printAnnotations(this.annotationsOnDimensions[i], output);
+ printAnnotations(annotationsOnDimensions[i], output);
output.append(" "); //$NON-NLS-1$
}
output.append("[]"); //$NON-NLS-1$
@@ -603,9 +606,10 @@ public class ParameterizedSingleTypeReference extends ArrayTypeReference {
typeAnnotations[i].traverse(visitor, scope);
}
}
- if (this.annotationsOnDimensions != null) {
- for (int i = 0, max = this.annotationsOnDimensions.length; i < max; i++) {
- Annotation[] annotations2 = this.annotationsOnDimensions[i];
+ Annotation [][] annotationsOnDimensions = getAnnotationsOnDimensions(true);
+ if (annotationsOnDimensions != null) {
+ for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) {
+ Annotation[] annotations2 = annotationsOnDimensions[i];
if (annotations2 != null) {
for (int j = 0, max2 = annotations2.length; j < max2; j++) {
Annotation annotation = annotations2[j];
@@ -629,9 +633,10 @@ public class ParameterizedSingleTypeReference extends ArrayTypeReference {
typeAnnotations[i].traverse(visitor, scope);
}
}
- if (this.annotationsOnDimensions != null) {
- for (int i = 0, max = this.annotationsOnDimensions.length; i < max; i++) {
- Annotation[] annotations2 = this.annotationsOnDimensions[i];
+ Annotation [][] annotationsOnDimensions = getAnnotationsOnDimensions(true);
+ if (annotationsOnDimensions != null) {
+ for (int i = 0, max = annotationsOnDimensions.length; i < max; i++) {
+ Annotation[] annotations2 = annotationsOnDimensions[i];
for (int j = 0, max2 = annotations2.length; j < max2; j++) {
Annotation annotation = annotations2[j];
annotation.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
index 048aaeeb0..bc51c76e3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
@@ -27,6 +27,7 @@
* bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking
* Bug 415850 - [1.8] Ensure RunJDTCoreTests can cope with null annotations enabled
* Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Jesper S Moller <jesper@selskabet.org> - Contributions for
* bug 378674 - "The method can be declared as static" is wrong
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
@@ -411,7 +412,7 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
hasError = true;
} else {
receiverType = ((SingleTypeReference) this.type).resolveTypeEnclosing(scope, (ReferenceBinding) enclosingInstanceType);
- receiverType = checkIllegalNullAnnotation(scope, receiverType);
+ checkIllegalNullAnnotation(scope, receiverType);
if (receiverType != null && enclosingInstanceContainsCast) {
CastExpression.checkNeedForEnclosingInstanceCast(scope, this.enclosingInstance, enclosingInstanceType, receiverType);
}
@@ -422,7 +423,7 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
receiverType = scope.enclosingSourceType();
} else {
receiverType = this.type.resolveType(scope, true /* check bounds*/);
- receiverType = checkIllegalNullAnnotation(scope, receiverType);
+ checkIllegalNullAnnotation(scope, receiverType);
checkParameterizedAllocation: {
if (receiverType == null || !receiverType.isValidBinding()) break checkParameterizedAllocation;
if (this.type instanceof ParameterizedQualifiedTypeReference) { // disallow new X<String>.Y<Integer>()
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
index 95c56db9c..3c896c591 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedTypeReference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 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
@@ -58,20 +58,14 @@ public class QualifiedTypeReference extends TypeReference {
this.sourceEnd = (int)(this.sourcePositions[this.sourcePositions.length-1] & 0x00000000FFFFFFFFL ) ;
}
- public TypeReference copyDims(int dim){
- //return a type reference copy of me with some dimensions
- //warning : the new type ref has a null binding
- return new ArrayQualifiedTypeReference(this.tokens, dim, this.sourcePositions);
- }
-
- public TypeReference copyDims(int dim, Annotation[][] annotationsOnDimensions) {
- //return a type reference copy of me with some dimensions
- //warning : the new type ref has a null binding
- ArrayQualifiedTypeReference arrayQualifiedTypeReference = new ArrayQualifiedTypeReference(this.tokens, dim, annotationsOnDimensions, this.sourcePositions);
+ public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) {
+ int totalDimensions = this.dimensions() + additionalDimensions;
+ Annotation [][] allAnnotations = getMergedAnnotationsOnDimensions(additionalDimensions, additionalAnnotations);
+ ArrayQualifiedTypeReference arrayQualifiedTypeReference = new ArrayQualifiedTypeReference(this.tokens, totalDimensions, allAnnotations, this.sourcePositions);
+ arrayQualifiedTypeReference.annotations = this.annotations;
arrayQualifiedTypeReference.bits |= (this.bits & ASTNode.HasTypeAnnotations);
- if (annotationsOnDimensions != null) {
- arrayQualifiedTypeReference.bits |= ASTNode.HasTypeAnnotations;
- }
+ if (!isVarargs)
+ arrayQualifiedTypeReference.extendedDimensions = additionalDimensions;
return arrayQualifiedTypeReference;
}
@@ -153,14 +147,11 @@ public class QualifiedTypeReference extends TypeReference {
}
}
- protected void rejectAnnotationsOnStaticMemberQualififer(Scope scope, ReferenceBinding currentType, int tokenIndex) {
+ protected static void rejectAnnotationsOnStaticMemberQualififer(Scope scope, ReferenceBinding currentType, Annotation[] qualifierAnnot) {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=385137
- if (this.annotations != null && currentType.isMemberType() && currentType.isStatic()) {
- Annotation[] qualifierAnnot = this.annotations[tokenIndex - 1];
- if (qualifierAnnot != null) {
- scope.problemReporter().illegalTypeAnnotationsInStaticMemberAccess(qualifierAnnot[0],
- qualifierAnnot[qualifierAnnot.length - 1]);
- }
+ if (currentType.isMemberType() && currentType.isStatic() && qualifierAnnot != null && qualifierAnnot.length > 0) {
+ scope.problemReporter().illegalTypeAnnotationsInStaticMemberAccess(qualifierAnnot[0],
+ qualifierAnnot[qualifierAnnot.length - 1]);
}
}
@@ -230,7 +221,9 @@ public class QualifiedTypeReference extends TypeReference {
return null;
ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
if (qualifiedType != null) {
- rejectAnnotationsOnStaticMemberQualififer(scope, currentType, i);
+ if (this.annotations != null) {
+ rejectAnnotationsOnStaticMemberQualififer(scope, currentType, this.annotations[i-1]);
+ }
ReferenceBinding enclosingType = currentType.enclosingType();
if (enclosingType != null && enclosingType.erasure() != qualifiedType.erasure()) {
qualifiedType = enclosingType; // inherited member type, leave it associated with its enclosing rather than subtype
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
index 6dc9e6be5..b80d1b8bc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
@@ -81,6 +81,7 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat
}
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
+ this.actualMethodBinding = this.binding; // grab before synthetics come into play.
SourceTypeBinding sourceType = currentScope.enclosingSourceType();
if (this.receiverType.isArrayType()) {
if (isConstructorReference()) {
@@ -637,4 +638,10 @@ public class ReferenceExpression extends FunctionalExpression implements Invocat
tSam = t.getSingleAbstractMethod(this.enclosingScope);
return resultExpression.tIsMoreSpecific(tSam.returnType, sSam.returnType);
}
+
+ public org.eclipse.jdt.internal.compiler.lookup.MethodBinding getMethodBinding() {
+ if (this.actualMethodBinding == null) // array new/clone, no real binding.
+ this.actualMethodBinding = this.binding;
+ return this.actualMethodBinding;
+ }
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
index c2ab7bf48..9d0f40df1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java
@@ -32,8 +32,9 @@
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
* Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099
* Bug 416307 - [1.8][compiler][null] subclass with type parameter substitution confuses null checking
+ * Bug 417758 - [1.8][null] Null safety compromise during array creation.
* Jesper S Moller - Contributions for
- * bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
+ * bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -78,7 +79,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo);
this.expression.checkNPEbyUnboxing(currentScope, flowContext, flowInfo);
if (flowInfo.reachMode() == FlowInfo.REACHABLE)
- checkAgainstNullAnnotation(currentScope, flowContext, this.expression.nullStatus(flowInfo, flowContext));
+ checkAgainstNullAnnotation(currentScope, flowContext, flowInfo);
if (currentScope.compilerOptions().analyseResourceLeaks) {
FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.expression, flowInfo, flowContext);
if (trackingVariable != null) {
@@ -165,7 +166,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
flowContext.recordAbruptExit();
return FlowInfo.DEAD_END;
}
-void checkAgainstNullAnnotation(BlockScope scope, FlowContext flowContext, int nullStatus) {
+void checkAgainstNullAnnotation(BlockScope scope, FlowContext flowContext, FlowInfo flowInfo) {
+ int nullStatus = this.expression.nullStatus(flowInfo, flowContext);
long tagBits;
MethodBinding methodBinding = null;
boolean useTypeAnnotations = scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8;
@@ -178,12 +180,7 @@ void checkAgainstNullAnnotation(BlockScope scope, FlowContext flowContext, int n
return;
}
if (useTypeAnnotations) {
- NullAnnotationMatching annotationStatus = NullAnnotationMatching.analyse(methodBinding.returnType, this.expression.resolvedType, nullStatus);
- if (annotationStatus.isDefiniteMismatch()) {
- scope.problemReporter().nullityMismatchingTypeAnnotation(this.expression, this.expression.resolvedType, methodBinding.returnType, annotationStatus);
- } else if (annotationStatus.isUnchecked()) {
- flowContext.recordNullityMismatch(scope, this.expression, this.expression.resolvedType, methodBinding.returnType, nullStatus);
- }
+ checkAgainstNullTypeAnnotation(scope, methodBinding.returnType, this.expression, flowContext, flowInfo);
} else if (nullStatus != FlowInfo.NON_NULL) {
// if we can't prove non-null check against declared null-ness of the enclosing method:
if ((tagBits & TagBits.AnnotationNonNull) != 0) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
index 87d909d45..88b387d40 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
@@ -887,7 +887,7 @@ public VariableBinding nullAnnotatedVariableBinding(boolean supportTypeAnnotatio
case Binding.FIELD : // reading a field
case Binding.LOCAL : // reading a local variable
if (supportTypeAnnotations
- || (((VariableBinding)this.binding).tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) != 0)
+ || (((VariableBinding)this.binding).tagBits & TagBits.AnnotationNullMASK) != 0)
return (VariableBinding) this.binding;
}
return null;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
index acc228117..8d0517ed1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleTypeReference.java
@@ -43,21 +43,14 @@ public class SingleTypeReference extends TypeReference {
}
- public TypeReference copyDims(int dim){
- //return a type reference copy of me with some dimensions
- //warning : the new type ref has a null binding
-
- return new ArrayTypeReference(this.token, dim,(((long)this.sourceStart)<<32)+this.sourceEnd);
- }
-
- public TypeReference copyDims(int dim, Annotation[][] annotationsOnDimensions){
- //return a type reference copy of me with some dimensions
- //warning : the new type ref has a null binding
- ArrayTypeReference arrayTypeReference = new ArrayTypeReference(this.token, dim, annotationsOnDimensions, (((long)this.sourceStart)<<32)+this.sourceEnd);
+ public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) {
+ int totalDimensions = this.dimensions() + additionalDimensions;
+ Annotation [][] allAnnotations = getMergedAnnotationsOnDimensions(additionalDimensions, additionalAnnotations);
+ ArrayTypeReference arrayTypeReference = new ArrayTypeReference(this.token, totalDimensions, allAnnotations, (((long) this.sourceStart) << 32) + this.sourceEnd);
+ arrayTypeReference.annotations = this.annotations;
arrayTypeReference.bits |= (this.bits & ASTNode.HasTypeAnnotations);
- if (annotationsOnDimensions != null) {
- arrayTypeReference.bits |= ASTNode.HasTypeAnnotations;
- }
+ if (!isVarargs)
+ arrayTypeReference.extendedDimensions = additionalDimensions;
return arrayTypeReference;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
index 431d79194..19b2704fa 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Statement.java
@@ -29,6 +29,7 @@
* Bug 415291 - [1.8][null] differentiate type incompatibilities due to null annotations
* Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
* Bug 416307 - [1.8][compiler][null] subclass with type parameter substitution confuses null checking
+ * Bug 417758 - [1.8][null] Null safety compromise during array creation.
* Andy Clement - Contributions for
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
* Bug 409250 - [1.8][compiler] Various loose ends in 308 code generation
@@ -156,6 +157,16 @@ void analyseOneArgument18(BlockScope currentScope, FlowContext flowContext, Flow
}
}
+protected void checkAgainstNullTypeAnnotation(BlockScope scope, TypeBinding requiredType, Expression expression, FlowContext flowContext, FlowInfo flowInfo) {
+ int nullStatus = expression.nullStatus(flowInfo, flowContext);
+ NullAnnotationMatching annotationStatus = NullAnnotationMatching.analyse(requiredType, expression.resolvedType, nullStatus);
+ if (annotationStatus.isDefiniteMismatch()) {
+ scope.problemReporter().nullityMismatchingTypeAnnotation(expression, expression.resolvedType, requiredType, annotationStatus);
+ } else if (annotationStatus.isUnchecked()) {
+ flowContext.recordNullityMismatch(scope, expression, expression.resolvedType, requiredType, nullStatus);
+ }
+}
+
/**
* INTERNAL USE ONLY.
* This is used to redirect inter-statements jumps.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
index a9d41fc9d..ad875f947 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
@@ -524,10 +524,10 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream) {
ExceptionLabel exceptionLabel = null;
if ((argument.binding.tagBits & TagBits.MultiCatchParameter) != 0) {
MultiCatchExceptionLabel multiCatchExceptionLabel = new MultiCatchExceptionLabel(codeStream, argument.binding.type);
- multiCatchExceptionLabel.initialize((UnionTypeReference) argument.type);
+ multiCatchExceptionLabel.initialize((UnionTypeReference) argument.type, argument.annotations);
exceptionLabel = multiCatchExceptionLabel;
} else {
- exceptionLabel = new ExceptionLabel(codeStream, argument.binding.type, argument.type);
+ exceptionLabel = new ExceptionLabel(codeStream, argument.binding.type, argument.type, argument.annotations);
}
exceptionLabel.placeStart();
exceptionLabels[i] = exceptionLabel;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
index 2eb350bde..4214bf69d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
@@ -19,6 +19,7 @@
* bug 392384 - [1.8][compiler][null] Restore nullness info from type annotations in class files
* Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099
* Bug 415850 - [1.8] Ensure RunJDTCoreTests can cope with null annotations enabled
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
* Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator
@@ -65,9 +66,8 @@ public abstract class TypeReference extends Expression {
public static final TypeReference[] NO_TYPE_ARGUMENTS = new TypeReference[0];
static class AnnotationCollector extends ASTVisitor {
List annotationContexts;
- TypeReference typeReference;
+ Expression typeReference;
int targetType;
- Annotation[] primaryAnnotations;
int info = 0;
int info2 = 0;
LocalVariableBinding localVariable;
@@ -83,7 +83,6 @@ static class AnnotationCollector extends ASTVisitor {
this.annotationContexts = annotationContexts;
this.typeReference = typeParameter.type;
this.targetType = targetType;
- this.primaryAnnotations = typeParameter.annotations;
this.info = typeParameterIndex;
}
@@ -95,7 +94,6 @@ static class AnnotationCollector extends ASTVisitor {
this.annotationContexts = annotationContexts;
this.typeReference = localDeclaration.type;
this.targetType = targetType;
- this.primaryAnnotations = localDeclaration.annotations;
this.localVariable = localVariable;
}
@@ -107,39 +105,10 @@ static class AnnotationCollector extends ASTVisitor {
this.annotationContexts = annotationContexts;
this.typeReference = localDeclaration.type;
this.targetType = targetType;
- this.primaryAnnotations = localDeclaration.annotations;
this.info = parameterIndex;
}
public AnnotationCollector(
- MethodDeclaration methodDeclaration,
- int targetType,
- List annotationContexts) {
- this.annotationContexts = annotationContexts;
- this.typeReference = methodDeclaration.returnType;
- this.targetType = targetType;
- this.primaryAnnotations = methodDeclaration.annotations;
- }
-
- public AnnotationCollector(
- ConstructorDeclaration constructorDeclaration,
- int targetType,
- List annotationContexts) {
- this.annotationContexts = annotationContexts;
- this.targetType = targetType;
- this.primaryAnnotations = constructorDeclaration.annotations;
- }
-
- public AnnotationCollector(
- FieldDeclaration fieldDeclaration,
- int targetType,
- List annotationContexts) {
- this.annotationContexts = annotationContexts;
- this.typeReference = fieldDeclaration.type;
- this.targetType = targetType;
- this.primaryAnnotations = fieldDeclaration.annotations;
- }
- public AnnotationCollector(
TypeReference typeReference,
int targetType,
List annotationContexts) {
@@ -148,7 +117,7 @@ static class AnnotationCollector extends ASTVisitor {
this.targetType = targetType;
}
public AnnotationCollector(
- TypeReference typeReference,
+ Expression typeReference,
int targetType,
int info,
List annotationContexts) {
@@ -192,9 +161,9 @@ static class AnnotationCollector extends ASTVisitor {
private boolean internalVisit(Annotation annotation) {
AnnotationContext annotationContext = null;
if (annotation.isRuntimeTypeInvisible()) {
- annotationContext = new AnnotationContext(annotation, this.typeReference, this.targetType, this.primaryAnnotations, AnnotationContext.INVISIBLE, this.annotationsOnDimensions, this.dimensions);
+ annotationContext = new AnnotationContext(annotation, this.typeReference, this.targetType, AnnotationContext.INVISIBLE);
} else if (annotation.isRuntimeTypeVisible()) {
- annotationContext = new AnnotationContext(annotation, this.typeReference, this.targetType, this.primaryAnnotations, AnnotationContext.VISIBLE, this.annotationsOnDimensions, this.dimensions);
+ annotationContext = new AnnotationContext(annotation, this.typeReference, this.targetType, AnnotationContext.VISIBLE);
}
if (annotationContext != null) {
annotationContext.wildcard = this.currentWildcard;
@@ -375,17 +344,46 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
public void checkBounds(Scope scope) {
// only parameterized type references have bounds
}
-public abstract TypeReference copyDims(int dim);
-public abstract TypeReference copyDims(int dim, Annotation[][] annotationsOnDimensions);
+public abstract TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs);
+
+protected Annotation[][] getMergedAnnotationsOnDimensions(int additionalDimensions, Annotation[][] additionalAnnotations) {
+ /* Note, we actually concatenate the additional annotations after base annotations, in bindings, they should appear before base annotations.
+ Given @English int @Nullable [] x @NonNull []; the type x is a @NonNull arrays of of @Nullable arrays of @English Strings, not the other
+ way about. Changing this in the compiler AST representation will cause too many ripples, so we leave it as is. On the bindings, the type
+ will reflect rotated (i.e will reflect correctly). See AnnotatableTypeSystem.flattenedAnnotations
+ */
+ Annotation[][] annotationsOnDimensions = this.getAnnotationsOnDimensions(true);
+ int dimensions = this.dimensions();
+
+ if (annotationsOnDimensions == null && additionalAnnotations == null)
+ return null;
+
+ final int totalDimensions = dimensions + additionalDimensions;
+ Annotation [][] mergedAnnotations = new Annotation[totalDimensions][];
+ if (annotationsOnDimensions != null) {
+ for (int i = 0; i < dimensions; i++) {
+ mergedAnnotations[i] = annotationsOnDimensions[i];
+ }
+ }
+ if (additionalAnnotations != null) {
+ for (int i = dimensions, j = 0; i < totalDimensions; i++, j++) {
+ mergedAnnotations[i] = additionalAnnotations[j];
+ }
+ }
+ return mergedAnnotations;
+}
+
public int dimensions() {
return 0;
}
+
//{ObjectTeams: synthetic AST can use TypeReference as receiver for static method:
@Override
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
// nop
}
// SH}
+
public AnnotationContext[] getAllAnnotationContexts(int targetType) {
List allAnnotationContexts = new ArrayList();
AnnotationCollector collector = new AnnotationCollector(this, targetType, allAnnotationContexts);
@@ -402,6 +400,14 @@ public void getAllAnnotationContexts(int targetType, int info, List allAnnotatio
AnnotationCollector collector = new AnnotationCollector(this, targetType, info, allAnnotationContexts);
this.traverse(collector, (BlockScope) null);
}
+public void getAllAnnotationContexts(int targetType, int info, List allAnnotationContexts, Annotation [] se7Annotations) {
+ AnnotationCollector collector = new AnnotationCollector(this, targetType, info, allAnnotationContexts);
+ for (int i = 0, length = se7Annotations == null ? 0 : se7Annotations.length; i < length; i++) {
+ Annotation annotation = se7Annotations[i];
+ annotation.traverse(collector, (BlockScope) null);
+ }
+ this.traverse(collector, (BlockScope) null);
+}
/**
* info can be either a type index (superclass/superinterfaces) or a pc into the bytecode
*/
@@ -428,6 +434,22 @@ public void getAllAnnotationContexts(int targetType, List allAnnotationContexts)
this.traverse(collector, (BlockScope) null);
}
public Annotation[][] getAnnotationsOnDimensions() {
+ return getAnnotationsOnDimensions(false);
+}
+
+public TypeReference [][] getTypeArguments() {
+ return null;
+}
+/**
+ * @param useSourceOrder if true annotations on dimensions are returned in source order, otherwise they are returned per
+ * how they ought to be interpreted by a type system, or external persistence view. For example, given the following:
+ * int @Nullable [] f @NonNull [] ==> f is really a @NonNull array of @Nullable arrays of ints. This is the type system
+ * view since extended dimensions bind more readily than type components that precede the identifier. This is how it ought
+ * to be encoded in bindings and how it ought to be persisted in class files. However for DOM/AST construction, we need the
+ * dimensions in source order, so we provide a way for the clients to ask what they want.
+ *
+ */
+public Annotation[][] getAnnotationsOnDimensions(boolean useSourceOrder) {
return null;
}
@@ -628,6 +650,12 @@ public boolean isDeclaredLifting() {
public boolean isWildcard() {
return false;
}
+public boolean isUnionType() {
+ return false;
+}
+public boolean isVarargs() {
+ return (this.bits & ASTNode.IsVarArgs) != 0;
+}
public boolean isParameterizedTypeReference() {
return false;
}
@@ -759,7 +787,7 @@ protected void checkNullConstraints(Scope scope, TypeReference[] typeArguments)
protected void checkNullConstraints(Scope scope, TypeBinding[] variables, int rank) {
if (variables != null && variables.length > rank) {
if (variables[rank].hasNullTypeAnnotations()) {
- if ((this.resolvedType.tagBits & TagBits.AnnotationNullMASK) != (variables[rank].tagBits & TagBits.AnnotationNullMASK)) {
+ if (NullAnnotationMatching.validNullTagBits(this.resolvedType.tagBits) != NullAnnotationMatching.validNullTagBits(variables[rank].tagBits)) {
scope.problemReporter().nullityMismatchTypeArgument(variables[rank], this.resolvedType, this);
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnionTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnionTypeReference.java
index 9a4e07c4b..945d55322 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnionTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnionTypeReference.java
@@ -34,13 +34,6 @@ public class UnionTypeReference extends TypeReference {
}
/* (non-Javadoc)
- * @see org.eclipse.jdt.internal.compiler.ast.TypeReference#copyDims(int)
- */
- public TypeReference copyDims(int dim) {
- return this; // arrays are not legal as union types.
- }
-
- /* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getLastToken()
*/
public char[] getLastToken() {
@@ -159,8 +152,10 @@ public class UnionTypeReference extends TypeReference {
}
return output;
}
-
- public TypeReference copyDims(int dim, Annotation[][] annotationsOnDimensions) {
+ public boolean isUnionType() {
+ return true;
+ }
+ public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) {
return this; // arrays are not legal as union types.
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java
index 5235cde38..4bf06d185 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Wildcard.java
@@ -15,6 +15,7 @@
* Bug 415397 - [1.8][compiler] Type Annotations on wildcard type argument dropped
* Stephan Herrmann - Contribution for
* Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -78,8 +79,6 @@ public class Wildcard extends SingleTypeReference {
if (((boundType.tagBits | this.resolvedType.tagBits) & TagBits.AnnotationNullMASK) == TagBits.AnnotationNullMASK) { // are both set?
Annotation annotation = this.bound.findAnnotation(boundType.tagBits & TagBits.AnnotationNullMASK);
scope.problemReporter().contradictoryNullAnnotationsOnBounds(annotation, this.resolvedType.tagBits);
- this.resolvedType = this.resolvedType.unannotated();
- this.bound.resolvedType = ((WildcardBinding)this.resolvedType).bound = boundType.unannotated();
}
}
return this.resolvedType;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java
index 1b7b52e65..e77920b2d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/TypeAnnotationWalker.java
@@ -16,7 +16,6 @@ package org.eclipse.jdt.internal.compiler.classfmt;
import org.eclipse.jdt.internal.compiler.codegen.AnnotationTargetTypeConstants;
import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
-import org.eclipse.jdt.internal.compiler.env.IBinaryMethod;
import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation;
/**
@@ -36,12 +35,13 @@ public class TypeAnnotationWalker {
* At the end of any walk an empty array of annotations is returned.
*/
public static final TypeAnnotationWalker EMPTY_ANNOTATION_WALKER = new TypeAnnotationWalker(new IBinaryTypeAnnotation[0], 0L) {
+ public TypeAnnotationWalker toField() { return this; }
public TypeAnnotationWalker toTarget(int targetType) { return this; }
public TypeAnnotationWalker toThrows(int rank) { return this; }
public TypeAnnotationWalker toTypeArgument(int rank) { return this; }
public TypeAnnotationWalker toMethodParameter(short index) { return this; }
public TypeAnnotationWalker toSupertype(short index) { return this; }
- public TypeAnnotationWalker toTypeBarameterBounds(boolean isClassTypeParameter, int parameterRank) { return this; }
+ public TypeAnnotationWalker toTypeParameterBounds(boolean isClassTypeParameter, int parameterRank) { return this; }
public TypeAnnotationWalker toTypeBound(short boundIndex) { return this; }
public TypeAnnotationWalker toTypeParameter(boolean isClassTypeParameter, int rank) { return this; }
public TypeAnnotationWalker toNextDetail(int detailKind) { return this; }
@@ -53,7 +53,7 @@ public class TypeAnnotationWalker {
final private int pathPtr; // pointer into the typePath
// precondition: not-empty typeAnnotations
- private TypeAnnotationWalker(IBinaryTypeAnnotation[] typeAnnotations) {
+ public TypeAnnotationWalker(IBinaryTypeAnnotation[] typeAnnotations) {
this(typeAnnotations, -1L >>> (64-typeAnnotations.length)); // initialize so lowest length bits are 1
}
TypeAnnotationWalker(IBinaryTypeAnnotation[] typeAnnotations, long matchBits) {
@@ -72,19 +72,6 @@ public class TypeAnnotationWalker {
return new TypeAnnotationWalker(this.typeAnnotations, newMatches, newPathPtr);
}
- /** Answer a walker for the given type annotations initialized to the root of the tree. */
- public static TypeAnnotationWalker create(IBinaryTypeAnnotation[] typeAnnotations) {
- if (typeAnnotations == null || typeAnnotations.length == 0)
- return EMPTY_ANNOTATION_WALKER;
- return new TypeAnnotationWalker(typeAnnotations);
- }
- /** Answer a walker for the type annotations of the given method initialized to the root of the tree. */
- public static TypeAnnotationWalker create(IBinaryMethod method) {
- if (method instanceof MethodInfoWithAnnotations)
- return create(((MethodInfoWithAnnotations) method).getTypeAnnotations());
- return EMPTY_ANNOTATION_WALKER;
- }
-
// ==== filter by top-level targetType: ====
/** Walk to a field. */
@@ -146,7 +133,7 @@ public class TypeAnnotationWalker {
* @param isClassTypeParameter whether we are looking at a class type parameter (else: method type type parameter)
* @param parameterRank rank of the type parameter.
*/
- public TypeAnnotationWalker toTypeBarameterBounds(boolean isClassTypeParameter, int parameterRank) {
+ public TypeAnnotationWalker toTypeParameterBounds(boolean isClassTypeParameter, int parameterRank) {
long newMatches = this.matches;
if (newMatches == 0)
return EMPTY_ANNOTATION_WALKER;
@@ -162,7 +149,7 @@ public class TypeAnnotationWalker {
return restrict(newMatches, 0);
}
/**
- * Detail of {@link #toTypeBarameterBounds(boolean, int)}: walk to the bounds
+ * Detail of {@link #toTypeParameterBounds(boolean, int)}: walk to the bounds
* of the previously selected type parameter.
* @param boundIndex
*/
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationContext.java
index c743d436f..865db3999 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/AnnotationContext.java
@@ -17,7 +17,7 @@
package org.eclipse.jdt.internal.compiler.codegen;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
-import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
@@ -25,34 +25,23 @@ public class AnnotationContext {
public static final int VISIBLE = 0x1;
public static final int INVISIBLE = 0x2;
public Annotation annotation;
- public TypeReference typeReference;
+ public Expression typeReference;
public int targetType;
public int info;
public int info2;
public int visibility;
- public Annotation[] primaryAnnotations;
public LocalVariableBinding variableBinding;
- public Annotation[][] annotationsOnDimensions;
public Wildcard wildcard;
- // annotationsOnDimensions might be null but the dimensions may still be important. In some
- // cases they are not on the reference.
- public int dimensions;
public AnnotationContext(
Annotation annotation,
- TypeReference typeReference,
+ Expression typeReference,
int targetType,
- Annotation[] primaryAnnotations,
- int visibility,
- Annotation[][] annotationsOnDimensions,
- int dimensions) {
+ int visibility) {
this.annotation = annotation;
this.typeReference = typeReference;
this.targetType = targetType;
- this.primaryAnnotations = primaryAnnotations;
this.visibility = visibility;
- this.annotationsOnDimensions = annotationsOnDimensions;
- this.dimensions = dimensions;
}
public String toString() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
index 06905c154..6b1ebdb82 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
@@ -37,7 +37,7 @@ import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
-import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
@@ -5930,8 +5930,7 @@ public void multianewarray(
TypeReference typeReference,
TypeBinding typeBinding,
int dimensions,
- int declaredDimensions,
- Annotation [][] annotationsOnDimensions) {
+ ArrayAllocationExpression allocationExpression) {
this.countLabels = 0;
this.stackDepth += (1 - dimensions);
if (this.classFileOffset + 3 >= this.bCodeStream.length) {
@@ -5986,7 +5985,7 @@ public void newArray(ArrayBinding arrayBinding) {
this.newArray(null, null, arrayBinding);
}
-public void newArray(TypeReference typeReference, Annotation[][] annotationsOnDimensions, ArrayBinding arrayBinding) {
+public void newArray(TypeReference typeReference, ArrayAllocationExpression allocationExpression, ArrayBinding arrayBinding) {
TypeBinding component = arrayBinding.elementsType();
switch (component.id) {
case TypeIds.T_int :
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
index 85246d2ea..ad91159f7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
@@ -15,6 +15,7 @@
* Bug 405066 - [1.8][compiler][codegen] Implement code generation infrastructure for JSR335
* Bug 406982 - [1.8][compiler] Generation of MethodParameters Attribute in classfile
* Bug 416885 - [1.8][compiler]IncompatibleClassChange error (edit)
+ * Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.codegen;
@@ -263,6 +264,8 @@ public class ConstantPool implements ClassFileConstants, TypeIds {
// Java 8 lambda support
public static final char[] METAFACTORY = "metafactory".toCharArray(); //$NON-NLS-1$
public static final char[] JAVA_LANG_INVOKE_LAMBDAMETAFACTORY_METAFACTORY_SIGNATURE = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;".toCharArray(); //$NON-NLS-1$
+ // Java 8 repeatable annotation support
+ public static final char[] JAVA_LANG_ANNOTATION_REPEATABLE = "Ljava/lang/annotation/Repeatable;".toCharArray(); //$NON-NLS-1$
public static final char[] HashCode = "hashCode".toCharArray(); //$NON-NLS-1$
public static final char[] HashCodeSignature = "()I".toCharArray(); //$NON-NLS-1$;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java
index e6e619d1f..ccc80639a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ExceptionLabel.java
@@ -17,6 +17,7 @@
package org.eclipse.jdt.internal.compiler.codegen;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
@@ -26,11 +27,13 @@ public class ExceptionLabel extends Label {
private int count = 0; // incremented each time placeStart or placeEnd is called
public TypeBinding exceptionType;
public TypeReference exceptionTypeReference;
+ public Annotation [] se7Annotations;
-public ExceptionLabel(CodeStream codeStream, TypeBinding exceptionType, TypeReference exceptionTypeReference) {
+public ExceptionLabel(CodeStream codeStream, TypeBinding exceptionType, TypeReference exceptionTypeReference, Annotation [] se7Annotations) {
super(codeStream);
this.exceptionType = exceptionType;
this.exceptionTypeReference = exceptionTypeReference;
+ this.se7Annotations = se7Annotations;
}
public ExceptionLabel(CodeStream codeStream, TypeBinding exceptionType) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/MultiCatchExceptionLabel.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/MultiCatchExceptionLabel.java
index 21fc79f2b..61587e190 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/MultiCatchExceptionLabel.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/MultiCatchExceptionLabel.java
@@ -18,6 +18,7 @@ package org.eclipse.jdt.internal.compiler.codegen;
import java.util.List;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
@@ -30,12 +31,12 @@ public class MultiCatchExceptionLabel extends ExceptionLabel {
super(codeStream, exceptionType);
}
- public void initialize(UnionTypeReference typeReference) {
+ public void initialize(UnionTypeReference typeReference, Annotation [] annotations) {
TypeReference[] typeReferences = typeReference.typeReferences;
int length = typeReferences.length;
this.exceptionLabels = new ExceptionLabel[length];
for (int i = 0; i < length; i++) {
- this.exceptionLabels[i] = new ExceptionLabel(this.codeStream, typeReferences[i].resolvedType, typeReferences[i]);
+ this.exceptionLabels[i] = new ExceptionLabel(this.codeStream, typeReferences[i].resolvedType, typeReferences[i], i == 0 ? annotations : null);
}
}
public void place() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/TypeAnnotationCodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/TypeAnnotationCodeStream.java
index bc66e5b48..e5342e9a2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/TypeAnnotationCodeStream.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/TypeAnnotationCodeStream.java
@@ -24,7 +24,7 @@ import java.util.List;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
-import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
@@ -40,8 +40,8 @@ public class TypeAnnotationCodeStream extends StackMapFrameCodeStream {
this.allTypeAnnotationContexts = new ArrayList();
}
- private void addAnnotationContext(TypeReference typeReference, int info, int targetType, Annotation[][] annotationsOnDimensions, int dimensions) {
- typeReference.getAllAnnotationContexts(targetType, info, this.allTypeAnnotationContexts, annotationsOnDimensions, dimensions);
+ private void addAnnotationContext(TypeReference typeReference, int info, int targetType, ArrayAllocationExpression allocationExpression) {
+ allocationExpression.getAllAnnotationContexts(targetType, info, this.allTypeAnnotationContexts);
}
private void addAnnotationContext(TypeReference typeReference, int info, int targetType) {
@@ -63,12 +63,11 @@ public class TypeAnnotationCodeStream extends StackMapFrameCodeStream {
TypeReference typeReference,
TypeBinding typeBinding,
int dimensions,
- int declaredDimensions,
- Annotation [][] annotationsOnDimensions) {
+ ArrayAllocationExpression allocationExpression) {
if (typeReference != null && (typeReference.bits & ASTNode.HasTypeAnnotations) != 0) {
- addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.NEW, annotationsOnDimensions, declaredDimensions);
+ addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.NEW, allocationExpression);
}
- super.multianewarray(typeReference, typeBinding, dimensions, declaredDimensions, annotationsOnDimensions);
+ super.multianewarray(typeReference, typeBinding, dimensions, allocationExpression);
}
public void new_(TypeReference typeReference, TypeBinding typeBinding) {
@@ -78,11 +77,11 @@ public class TypeAnnotationCodeStream extends StackMapFrameCodeStream {
super.new_(typeReference, typeBinding);
}
- public void newArray(TypeReference typeReference, Annotation[][] annotationsOnDimensions, ArrayBinding arrayBinding) {
+ public void newArray(TypeReference typeReference, ArrayAllocationExpression allocationExpression, ArrayBinding arrayBinding) {
if (typeReference != null && (typeReference.bits & ASTNode.HasTypeAnnotations) != 0) {
- addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.NEW, annotationsOnDimensions, arrayBinding.dimensions);
+ addAnnotationContext(typeReference, this.position, AnnotationTargetTypeConstants.NEW, allocationExpression);
}
- super.newArray(typeReference, annotationsOnDimensions, arrayBinding);
+ super.newArray(typeReference, allocationExpression, arrayBinding);
}
public void checkcast(TypeReference typeReference, TypeBinding typeBinding) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
index 4e04c1234..9ac3acabf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/impl/CompilerOptions.java
@@ -155,6 +155,8 @@ public class CompilerOptions {
public static final String OPTION_ReportOverridingMethodWithoutSuperInvocation = "org.eclipse.jdt.core.compiler.problem.overridingMethodWithoutSuperInvocation"; //$NON-NLS-1$
public static final String OPTION_GenerateClassFiles = "org.eclipse.jdt.core.compiler.generateClassFiles"; //$NON-NLS-1$
public static final String OPTION_Process_Annotations = "org.eclipse.jdt.core.compiler.processAnnotations"; //$NON-NLS-1$
+ // OPTION_Store_Annotations: undocumented option for testing purposes
+ public static final String OPTION_Store_Annotations = "org.eclipse.jdt.core.compiler.storeAnnotations"; //$NON-NLS-1$
public static final String OPTION_ReportRedundantSuperinterface = "org.eclipse.jdt.core.compiler.problem.redundantSuperinterface"; //$NON-NLS-1$
public static final String OPTION_ReportComparingIdentical = "org.eclipse.jdt.core.compiler.problem.comparingIdentical"; //$NON-NLS-1$
public static final String OPTION_ReportMissingSynchronizedOnInheritedMethod = "org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod"; //$NON-NLS-1$
@@ -1430,6 +1432,7 @@ public class CompilerOptions {
optionsMap.put(OPTION_ReportOverridingMethodWithoutSuperInvocation, getSeverityString(OverridingMethodWithoutSuperInvocation));
optionsMap.put(OPTION_GenerateClassFiles, this.generateClassFiles ? ENABLED : DISABLED);
optionsMap.put(OPTION_Process_Annotations, this.processAnnotations ? ENABLED : DISABLED);
+ optionsMap.put(OPTION_Store_Annotations, this.storeAnnotations ? ENABLED : DISABLED);
optionsMap.put(OPTION_ReportRedundantSuperinterface, getSeverityString(RedundantSuperinterface));
optionsMap.put(OPTION_ReportComparingIdentical, getSeverityString(ComparingIdentical));
optionsMap.put(OPTION_ReportMissingSynchronizedOnInheritedMethod, getSeverityString(MissingSynchronizedModifierInInheritedMethod));
@@ -2021,6 +2024,7 @@ public class CompilerOptions {
this.isAnnotationBasedNullAnalysisEnabled = ENABLED.equals(optionValue);
}
if (this.isAnnotationBasedNullAnalysisEnabled) {
+ this.storeAnnotations = true;
if ((optionValue = optionsMap.get(OPTION_ReportNullSpecViolation)) != null) {
if (ERROR.equals(optionValue)) {
this.errorThreshold.set(NullSpecViolation);
@@ -2161,7 +2165,16 @@ public class CompilerOptions {
this.storeAnnotations = true; // annotation processing requires annotation to be stored
} else if (DISABLED.equals(optionValue)) {
this.processAnnotations = false;
- this.storeAnnotations = false;
+ if (!this.isAnnotationBasedNullAnalysisEnabled)
+ this.storeAnnotations = false;
+ }
+ }
+ if ((optionValue = optionsMap.get(OPTION_Store_Annotations)) != null) {
+ if (ENABLED.equals(optionValue)) {
+ this.storeAnnotations = true;
+ } else if (DISABLED.equals(optionValue)) {
+ if (!this.isAnnotationBasedNullAnalysisEnabled && !this.processAnnotations)
+ this.storeAnnotations = false;
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java
index 60765bf72..73bb07c50 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotatableTypeSystem.java
@@ -14,6 +14,7 @@
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.DependentTypeBinding;
@@ -31,7 +32,7 @@ import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBindin
We do not keep track of unannotated types here, that is done by UTS whose handle we maintain.
*/
-public class AnnotatableTypeSystem {
+public class AnnotatableTypeSystem extends TypeSystem {
LookupEnvironment environment;
UnannotatedTypeSystem unannotatedTypeSystem;
@@ -48,44 +49,96 @@ public class AnnotatableTypeSystem {
return this.unannotatedTypeSystem.getUnannotatedType(type);
}
+ // Given a type, return all its variously annotated versions.
+ public TypeBinding[] getAnnotatedTypes(TypeBinding type) {
+
+ TypeBinding keyType = getUnannotatedType(type);
+ TypeBinding[] cachedInfo = (TypeBinding[]) this.annotatedTypes.get(keyType);
+ if (cachedInfo == null)
+ return Binding.NO_TYPES;
+
+ final int length = cachedInfo.length;
+ TypeBinding [] annotatedVersions = new TypeBinding[length];
+ int versions = 0;
+ for (int i = 0; i < length; i++) {
+ final TypeBinding cachedType = cachedInfo[i];
+ if (cachedType == null)
+ break;
+ if (cachedType.id == type.id)
+ annotatedVersions[versions++] = cachedType;
+ }
+
+ if (versions == 0)
+ return Binding.NO_TYPES;
+
+ if (versions != length)
+ System.arraycopy(annotatedVersions, 0, annotatedVersions = new TypeBinding[versions], 0, versions);
+
+ return annotatedVersions;
+ }
+
+ public ArrayBinding getArrayType(TypeBinding leaftType, int dimensions) {
+ return getArrayType(leaftType, dimensions, Binding.NO_ANNOTATIONS);
+ }
+
/* This method replaces the version that used to sit in LE. The parameter `annotations' is a flattened sequence of annotations,
where each dimension's annotations end with a sentinel null.
*/
- public ArrayBinding getArrayType(TypeBinding leafType, int dimensions, AnnotationBinding [] annotations) {
+ public ArrayBinding getArrayType(TypeBinding leafComponentType, int dimensions, AnnotationBinding [] annotations) {
- if (!haveTypeAnnotations(leafType, annotations))
- return this.unannotatedTypeSystem.getArrayType(leafType, dimensions);
+ if (!haveTypeAnnotations(leafComponentType, annotations))
+ return this.unannotatedTypeSystem.getArrayType(leafComponentType, dimensions);
- TypeBinding[] cachedInfo = (TypeBinding[]) this.annotatedTypes.get(leafType);
+ // Leaf component type can be an annotated type.
+ TypeBinding keyType = getUnannotatedType(leafComponentType);
+ TypeBinding[] cachedInfo = (TypeBinding[]) this.annotatedTypes.get(keyType); // unannotated key promotes better instance sharing.
int index = 0;
if (cachedInfo != null) {
for (int max = cachedInfo.length; index < max; index++) {
TypeBinding cachedType = cachedInfo[index];
if (cachedType == null) break;
+ if (cachedType.leafComponentType() != leafComponentType) continue;
if (cachedType.isArrayType() && cachedType.dimensions() == dimensions && Util.effectivelyEqual(cachedType.getTypeAnnotations(), annotations))
return (ArrayBinding) cachedType;
}
} else {
- this.annotatedTypes.put(leafType, cachedInfo = new TypeBinding[4]);
+ this.annotatedTypes.put(keyType, cachedInfo = new TypeBinding[4]);
}
int length = cachedInfo.length;
if (index == length) {
System.arraycopy(cachedInfo, 0, cachedInfo = new TypeBinding[length * 2], 0, length);
- this.annotatedTypes.put(leafType, cachedInfo);
+ this.annotatedTypes.put(keyType, cachedInfo);
}
// Add the newcomer, ensuring its identity is the same as the naked version of it.
- ArrayBinding unannotatedArrayType = this.unannotatedTypeSystem.getArrayType(leafType, dimensions);
- TypeBinding arrayBinding = new ArrayBinding(leafType, dimensions, this.environment);
+ ArrayBinding unannotatedArrayType = this.unannotatedTypeSystem.getArrayType(leafComponentType, dimensions);
+ TypeBinding arrayBinding = new ArrayBinding(leafComponentType, dimensions, this.environment);
arrayBinding.id = unannotatedArrayType.id;
arrayBinding.setTypeAnnotations(annotations, this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled);
return (ArrayBinding) (cachedInfo[index] = arrayBinding);
}
+
+ public ReferenceBinding getMemberType(ReferenceBinding memberType, ReferenceBinding enclosingType) {
+ if (!haveTypeAnnotations(memberType, enclosingType))
+ return this.unannotatedTypeSystem.getMemberType(memberType, enclosingType);
+ return (ReferenceBinding) getAnnotatedType(memberType, enclosingType, memberType.typeArguments(), memberType.getTypeAnnotations());
+ }
+
+//{ObjectTeams: 2 args added for role types:
+/* orig:
+ public ParameterizedTypeBinding getParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType) {
+ return getParameterizedType(genericType, typeArguments, enclosingType, Binding.NO_ANNOTATIONS);
+ :giro */
+ public ParameterizedTypeBinding getParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments,
+ ITeamAnchor teamAnchor, int valueParamPosition, ReferenceBinding enclosingType) {
+ return getParameterizedType(genericType, typeArguments, teamAnchor, valueParamPosition, enclosingType, Binding.NO_ANNOTATIONS);
+// SH}
+ }
- public ParameterizedTypeBinding getParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType, AnnotationBinding [] annotations) {
//{ObjectTeams: more arguments for role types:
- return getParameterizedType(genericType, typeArguments, null, -1, enclosingType, annotations);
- }
+/* orig:
+ public ParameterizedTypeBinding getParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType, AnnotationBinding [] annotations) {
+ :giro */
public ParameterizedTypeBinding getParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments,
ITeamAnchor teamAnchor, int valueParamPosition, ReferenceBinding enclosingType, AnnotationBinding [] annotations) {
if (teamAnchor == null && genericType instanceof DependentTypeBinding)
@@ -98,20 +151,9 @@ public class AnnotatableTypeSystem {
return this.unannotatedTypeSystem.getParameterizedType(genericType, typeArguments, teamAnchor, valueParamPosition, enclosingType);
// SH}
- /* When restoring annotations from class files, we encounter a situation where the generic type comes in attributed with the annotations that should
- really belong to the parameterized type that is being created just now. e.g @T List<String> => comes in as (@T List)<String>. The question really
- is List being parameterized by String and then the resultant type is annotated or is "@T List" being parameterized with String ? We don't care one
- way or other except that we would want a uniform treatment. As a stop gap, we "repair" the situation here, so it is consistent with treatment of
- type references in source code. Probably need similar treatment for raw types and wildcards ?
- */
- AnnotationBinding [] misplacedAnnotations = genericType.getTypeAnnotations();
- if (misplacedAnnotations != null && misplacedAnnotations != Binding.NO_ANNOTATIONS) {
- if (annotations != null && annotations != Binding.NO_ANNOTATIONS)
- throw new IllegalStateException(); // cannot cut both ways.
- annotations = misplacedAnnotations;
- genericType = (ReferenceBinding) this.unannotatedTypeSystem.getUnannotatedType(genericType);
- }
-
+ if (genericType.hasTypeAnnotations())
+ throw new IllegalStateException();
+
int index = 0;
TypeBinding[] cachedInfo = (TypeBinding[]) this.annotatedTypes.get(genericType);
if (cachedInfo != null) {
@@ -165,11 +207,18 @@ public class AnnotatableTypeSystem {
return (ParameterizedTypeBinding) (cachedInfo[index] = parameterizedType);
}
+ public RawTypeBinding getRawType(ReferenceBinding genericType, ReferenceBinding enclosingType) {
+ return getRawType(genericType, enclosingType, Binding.NO_ANNOTATIONS);
+ }
+
public RawTypeBinding getRawType(ReferenceBinding genericType, ReferenceBinding enclosingType, AnnotationBinding [] annotations) {
if (!haveTypeAnnotations(genericType, enclosingType, null, annotations))
return this.unannotatedTypeSystem.getRawType(genericType, enclosingType);
+ if (genericType.hasTypeAnnotations())
+ throw new IllegalStateException();
+
TypeBinding[] cachedInfo = (TypeBinding[]) this.annotatedTypes.get(genericType);
int index = 0;
if (cachedInfo != null) {
@@ -197,6 +246,10 @@ public class AnnotatableTypeSystem {
return (RawTypeBinding) (cachedInfo[index] = rawType);
}
+ public WildcardBinding getWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind) {
+ return getWildcard(genericType, rank, bound, otherBounds, boundKind, Binding.NO_ANNOTATIONS);
+ }
+
public WildcardBinding getWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind, AnnotationBinding [] annotations) {
if (!haveTypeAnnotations(genericType, bound, otherBounds, annotations))
@@ -205,7 +258,10 @@ public class AnnotatableTypeSystem {
if (genericType == null) // pseudo wildcard denoting composite bounds for lub computation
genericType = ReferenceBinding.LUB_GENERIC;
- TypeBinding[] cachedInfo = (TypeBinding[]) this.annotatedTypes.get(genericType);
+ if (genericType.hasTypeAnnotations())
+ throw new IllegalStateException();
+
+ TypeBinding[] cachedInfo = (TypeBinding[]) this.annotatedTypes.get(genericType); // promotes better instance sharing.
int index = 0;
if (cachedInfo != null) {
for (int max = cachedInfo.length; index < max; index++) {
@@ -236,9 +292,10 @@ public class AnnotatableTypeSystem {
return (WildcardBinding) (cachedInfo[index] = wildcard);
}
- // Private subroutine for getAnnotatedType(TypeBinding type, AnnotationBinding[][] annotations)
+ // Private subroutine for public APIs.
private TypeBinding getAnnotatedType(TypeBinding type, TypeBinding enclosingType, TypeBinding [] typeArguments, AnnotationBinding[] annotations) {
- TypeBinding[] cachedInfo = (TypeBinding[]) this.annotatedTypes.get(type);
+ TypeBinding keyType = getUnannotatedType(type);
+ TypeBinding[] cachedInfo = (TypeBinding[]) this.annotatedTypes.get(keyType);
int i = 0;
if (cachedInfo != null) {
for (int length = cachedInfo.length; i < length; i++) {
@@ -251,20 +308,20 @@ public class AnnotatableTypeSystem {
}
}
} else {
- this.annotatedTypes.put(type, cachedInfo = new TypeBinding[4]);
+ this.annotatedTypes.put(keyType, cachedInfo = new TypeBinding[4]);
}
int length = cachedInfo.length;
if (i == length) {
System.arraycopy(cachedInfo, 0, cachedInfo = new TypeBinding[length * 2], 0, length);
- this.annotatedTypes.put(type, cachedInfo);
+ this.annotatedTypes.put(keyType, cachedInfo);
}
/* Add the new comer, retaining the same type binding id as the naked type. To materialize the new comer we can't use new since this is a general
- purpose method designed to deal type bindings of all types. "Clone" the incoming type, specializing for any enclosing type and type arguments
- that may themselves be possibly be annotated. This is so the binding for @Outer Outer.Inner != Outer.@Inner Inner != @Outer Outer.@Inner Inner.
- Likewise so the bindings for @Readonly List<@NonNull String> != @Readonly List<@Nullable String> != @Readonly List<@Interned String>
+ purpose method designed to deal type bindings of all types. "Clone" the incoming type, specializing for any enclosing type that may itself be
+ possibly be annotated. This is so the binding for @Outer Outer.Inner != Outer.@Inner Inner != @Outer Outer.@Inner Inner. Likewise so the bindings
+ for @Readonly List<@NonNull String> != @Readonly List<@Nullable String> != @Readonly List<@Interned String>
*/
TypeBinding unannotatedType = this.unannotatedTypeSystem.getUnannotatedType(type);
- TypeBinding annotatedType = type.clone(enclosingType, typeArguments);
+ TypeBinding annotatedType = type.clone(enclosingType);
annotatedType.id = unannotatedType.id;
annotatedType.setTypeAnnotations(annotations, this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled);
return cachedInfo[i] = annotatedType;
@@ -298,6 +355,10 @@ public class AnnotatableTypeSystem {
java.lang.@T X.@T Y.@T Z
in all these cases the incoming type binding is for Z, but annotations are for different levels. Align their layout for proper attribution.
*/
+
+ if (type.isUnresolvedType() && CharOperation.indexOf('$', type.sourceName()) > 0)
+ type = BinaryTypeBinding.resolveType(type, this.environment, true); // must resolve member types before asking for enclosingType
+
int levels = type.depth() + 1;
TypeBinding [] types = new TypeBinding[levels];
types[--levels] = type;
@@ -317,16 +378,21 @@ public class AnnotatableTypeSystem {
return type;
// types[j] is the first component being annotated. Its annotations are annotations[i]
for (enclosingType = j == 0 ? null : types[j - 1]; i < levels; i++, j++) {
- annotatedType = getAnnotatedType(types[j], enclosingType, types[j].typeArguments(), annotations[i]);
+ final TypeBinding currentType = types[j];
+ // while handling annotations from SE7 locations, take care not to drop existing annotations.
+ AnnotationBinding [] currentAnnotations = annotations[i] != null && annotations[i].length > 0 ? annotations[i] : currentType.getTypeAnnotations();
+ annotatedType = getAnnotatedType(currentType, enclosingType, currentType.typeArguments(), currentAnnotations);
enclosingType = annotatedType;
}
break;
+ default:
+ throw new IllegalStateException();
}
return annotatedType;
}
- public AnnotationBinding getAnnotationType(ReferenceBinding annotationType) {
- return this.unannotatedTypeSystem.getAnnotationType(annotationType); // deflect, annotation type uses cannot be type annotated.
+ public AnnotationBinding getAnnotationType(ReferenceBinding annotationType, boolean requireResolved) {
+ return this.unannotatedTypeSystem.getAnnotationType(annotationType, requireResolved); // deflect, annotation type uses cannot be type annotated.
}
private boolean haveTypeAnnotations(TypeBinding baseType, TypeBinding someType, TypeBinding[] someTypes, AnnotationBinding[] annotations) {
@@ -346,6 +412,10 @@ public class AnnotatableTypeSystem {
private boolean haveTypeAnnotations(TypeBinding leafType, AnnotationBinding[] annotations) {
return haveTypeAnnotations(leafType, null, null, annotations);
}
+
+ private boolean haveTypeAnnotations(TypeBinding memberType, TypeBinding enclosingType) {
+ return haveTypeAnnotations(memberType, enclosingType, null, null);
+ }
/* Utility method to "flatten" annotations. For multidimensional arrays, we encode the annotations into a flat array
where a null separates the annotations of dimension n from dimension n - 1 as well as dimenion n + 1. There is a
@@ -396,4 +466,8 @@ public class AnnotatableTypeSystem {
}
this.unannotatedTypeSystem.updateCaches(unresolvedType.prototype, unresolvedType.prototype.resolvedType);
}
+
+ public boolean isAnnotatedTypeSystem() {
+ return true;
+ }
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java
index 038c5ade8..e9f1d8663 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationBinding.java
@@ -1,10 +1,14 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 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
*******************************************************************************/
@@ -195,6 +199,10 @@ public ReferenceBinding getAnnotationType() {
return this.type;
}
+public void resolve() {
+ // Nothing to do, this is already resolved.
+}
+
public ElementValuePair[] getElementValuePairs() {
return this.pairs;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
index 6091c972c..e8782d519 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ArrayBinding.java
@@ -20,6 +20,7 @@
* Bug 415291 - [1.8][null] differentiate type incompatibilities due to null annotations
* Bug 415850 - [1.8] Ensure RunJDTCoreTests can cope with null annotations enabled
* Bug 416176 - [1.8][compiler][null] null type annotations cause grief on type variables
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -306,8 +307,7 @@ public char[] nullAnnotatedReadableName(CompilerOptions options, boolean shortNa
brackets[i] = new char[]{'[', ']'};
}
}
- char[] leafTypeName = shortNames ? this.leafComponentType.shortReadableName() : this.leafComponentType.readableName();
- return CharOperation.concat(leafTypeName,
+ return CharOperation.concat(this.leafComponentType.nullAnnotatedReadableName(options, shortNames),
CharOperation.concatWith(brackets, ' '),
' ');
}
@@ -343,9 +343,10 @@ public char[] readableName() /* java.lang.Object[] */ {
}
public void setTypeAnnotations(AnnotationBinding[] annotations, boolean evalNullAnnotations) {
-
+ this.tagBits |= TagBits.HasTypeAnnotations;
+ if (annotations == null || annotations.length == 0)
+ return;
this.typeAnnotations = annotations;
- this.tagBits |= TagBits.HasTypeAnnotations | TagBits.HasTypeAnnotations;
if (evalNullAnnotations) {
long nullTagBits = 0;
@@ -412,7 +413,7 @@ public TypeBinding maybeWrapRoleType(ASTNode typedNode, TypeArgumentUpdater upda
}
// SH}
public String toString() {
- return this.leafComponentType != null ? this.hasTypeAnnotations() ? annotatedDebugName() : debugName() : "NULL TYPE ARRAY"; //$NON-NLS-1$
+ return this.leafComponentType != null ? debugName() : "NULL TYPE ARRAY"; //$NON-NLS-1$
}
public TypeBinding unannotated() {
return this.hasTypeAnnotations() ? this.environment.getUnannotatedType(this) : this;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java
index 1bc3bc92d..5238d000c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BaseTypeBinding.java
@@ -13,6 +13,7 @@
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for
* bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -134,12 +135,6 @@ public final class BaseTypeBinding extends TypeBinding {
this.simpleName = name;
this.constantPoolName = constantPoolName;
}
-
- BaseTypeBinding(BaseTypeBinding prototype) {
- super(prototype);
- this.simpleName = prototype.simpleName;
- this.constantPoolName = prototype.constantPoolName;
- }
/**
* int -> I
@@ -155,8 +150,8 @@ public final class BaseTypeBinding extends TypeBinding {
return this.constantPoolName;
}
- public TypeBinding clone(TypeBinding enclosingType, TypeBinding[] typeArguments) {
- return new BaseTypeBinding(this);
+ public TypeBinding clone(TypeBinding enclosingType) {
+ return new BaseTypeBinding(this.id, this.simpleName, this.constantPoolName);
}
public PackageBinding getPackage() {
@@ -177,7 +172,13 @@ public final class BaseTypeBinding extends TypeBinding {
return this == TypeBinding.NULL && !right.isBaseType();
}
+ public void setTypeAnnotations(AnnotationBinding[] annotations, boolean evalNullAnnotations) {
+ super.setTypeAnnotations(annotations, false); // never set nullTagBits on base types
+ }
+
public TypeBinding unannotated() {
+ if (!this.hasTypeAnnotations())
+ return this;
switch (this.id) {
case TypeIds.T_boolean:
return TypeBinding.BOOLEAN;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index b7ad5af7d..4c92d8b89 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -27,8 +27,10 @@
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
* Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099
* Bug 415850 - [1.8] Ensure RunJDTCoreTests can cope with null annotations enabled
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Jesper Steen Moller - Contributions for
* Bug 412150 [1.8] [compiler] Enable reflected parameter names during annotation processing
+ * Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -42,11 +44,12 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.FieldInfo;
import org.eclipse.jdt.internal.compiler.classfmt.MethodInfo;
import org.eclipse.jdt.internal.compiler.classfmt.TypeAnnotationWalker;
-import org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.Util;
@@ -132,13 +135,15 @@ public class BinaryTypeBinding extends ReferenceBinding {
protected MethodBinding[] methods;
protected ReferenceBinding[] memberTypes;
protected TypeVariableBinding[] typeVariables;
- protected BinaryTypeBinding prototype;
+ private BinaryTypeBinding prototype;
// For the link with the principle structure
protected LookupEnvironment environment;
protected SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder
+ private ReferenceBinding containingAnnotation;
+
//{ObjectTeams: support callout-to-field
/** Callout to field adds faked access method (set or get): */
@@ -219,15 +224,9 @@ static Object convertMemberValue(Object binaryValue, LookupEnvironment env, char
throw new IllegalStateException();
}
-public TypeBinding clone(TypeBinding outerType, TypeBinding[] typeArguments) {
+public TypeBinding clone(TypeBinding outerType) {
BinaryTypeBinding copy = new BinaryTypeBinding(this);
-
copy.enclosingType = (ReferenceBinding) outerType;
- if (outerType instanceof UnresolvedReferenceBinding)
- copy.tagBits |= TagBits.HasUnresolvedEnclosingType;
- else
- copy.tagBits &= ~TagBits.HasUnresolvedEnclosingType;
-
return copy;
}
@@ -367,8 +366,11 @@ public BinaryTypeBinding(PackageBinding packageBinding, IBinaryType binaryType,
*/
public FieldBinding[] availableFields() {
- if (this != this.prototype)
+ if (this != this.prototype) {
+ if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
+ return this.fields;
return this.prototype.availableFields();
+ }
if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
return this.fields;
@@ -396,6 +398,7 @@ public FieldBinding[] availableFields() {
}
private TypeVariableBinding[] addMethodTypeVariables(TypeVariableBinding[] methodTypeVars) {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.typeVariables == null || this.typeVariables == Binding.NO_TYPE_VARIABLES) {
return methodTypeVars;
}
@@ -425,8 +428,11 @@ private TypeVariableBinding[] addMethodTypeVariables(TypeVariableBinding[] metho
*/
public MethodBinding[] availableMethods() {
- if (this != this.prototype)
+ if (this != this.prototype) {
+ if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
+ return this.methods;
return this.prototype.availableMethods();
+ }
if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
return this.methods;
@@ -454,6 +460,7 @@ public MethodBinding[] availableMethods() {
}
void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
+ if (this != this.prototype) throw new IllegalStateException();
try {
// default initialization for super-interfaces early, in case some aborting compilation error occurs,
// and still want to use binaries passed that point (e.g. type hierarchy resolver, see bug 63748).
@@ -521,7 +528,7 @@ void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
and/or super interfaces in order to be able to detect overriding in the presence
of generics.
*/
- TypeAnnotationWalker walker = sourceLevel >= ClassFileConstants.JDK1_8 ? TypeAnnotationWalker.create(binaryType.getTypeAnnotations()) : TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
+ TypeAnnotationWalker walker = getTypeAnnotationWalker(binaryType.getTypeAnnotations());
char[] typeSignature = binaryType.getGenericSignature(); // use generic signature even in 1.4
this.tagBits |= binaryType.getTagBits();
@@ -655,6 +662,8 @@ void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
// SH}
if (this.environment.globalOptions.storeAnnotations)
setAnnotations(createAnnotations(binaryType.getAnnotations(), this.environment, missingTypeNames));
+ if (this.isAnnotationType())
+ scanTypeForContainerAnnotation(binaryType, missingTypeNames);
} finally {
// protect against incorrect use of the needFieldsAndMethods flag, see 48459
if (this.fields == null)
@@ -664,20 +673,28 @@ void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
}
}
+private TypeAnnotationWalker getTypeAnnotationWalker(IBinaryTypeAnnotation[] annotations) {
+ if (this != this.prototype) throw new IllegalStateException();
+ if (annotations == null || annotations.length == 0)
+ return TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
+
+ return this.environment.usesAnnotatedTypeSystem() ? new TypeAnnotationWalker(annotations) : TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
+}
+
private void createFields(IBinaryField[] iFields, long sourceLevel, char[][][] missingTypeNames) {
+ if (this != this.prototype) throw new IllegalStateException();
this.fields = Binding.NO_FIELDS;
if (iFields != null) {
int size = iFields.length;
if (size > 0) {
this.fields = new FieldBinding[size];
boolean use15specifics = sourceLevel >= ClassFileConstants.JDK1_5;
- boolean use18specifics = sourceLevel >= ClassFileConstants.JDK1_8;
boolean hasRestrictedAccess = hasRestrictedAccess();
int firstAnnotatedFieldIndex = -1;
for (int i = 0; i < size; i++) {
IBinaryField binaryField = iFields[i];
char[] fieldSignature = use15specifics ? binaryField.getGenericSignature() : null;
- TypeAnnotationWalker walker = use18specifics ? TypeAnnotationWalker.create(binaryField.getTypeAnnotations()).toField() : TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
+ TypeAnnotationWalker walker = getTypeAnnotationWalker(binaryField.getTypeAnnotations()).toField();
TypeBinding type = fieldSignature == null
? this.environment.getTypeFromSignature(binaryField.getTypeName(), 0, -1, false, this, missingTypeNames, walker)
: this.environment.getTypeFromTypeSignature(new SignatureWrapper(fieldSignature), Binding.NO_TYPE_VARIABLES, this, missingTypeNames, walker);
@@ -758,6 +775,7 @@ private MethodBinding createMethod(IBinaryMethod method, long sourceLevel, char[
MethodBinding result = null;
try {
// SH}
+ if (this != this.prototype) throw new IllegalStateException();
int methodModifiers = method.getModifiers() | ExtraCompilerModifiers.AccUnresolved;
if (sourceLevel < ClassFileConstants.JDK1_5)
methodModifiers &= ~ClassFileConstants.AccVarargs; // vararg methods are not recognized until 1.5
@@ -782,7 +800,7 @@ private MethodBinding createMethod(IBinaryMethod method, long sourceLevel, char[
variables properly in order to be able to apply substitutions and thus be able to detect
overriding in the presence of generics. Seeing the erased form is not good enough.
*/
- TypeAnnotationWalker walker = sourceLevel >= ClassFileConstants.JDK1_8 ? TypeAnnotationWalker.create(method) : TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
+ TypeAnnotationWalker walker = getTypeAnnotationWalker(method.getTypeAnnotations());
char[] methodSignature = method.getGenericSignature(); // always use generic signature, even in 1.4
if (methodSignature == null) { // no generics
char[] methodDescriptor = method.getMethodDescriptor(); // of the form (I[Ljava/jang/String;)V
@@ -1013,6 +1031,7 @@ private MethodBinding createMethod(IBinaryMethod method, long sourceLevel, char[
* iMethods for which MethodBindings have been created; indices match those in this.methods.
*/
private IBinaryMethod[] createMethods(IBinaryMethod[] iMethods, long sourceLevel, char[][][] missingTypeNames) {
+ if (this != this.prototype) throw new IllegalStateException();
int total = 0, initialTotal = 0, iClinit = -1;
int[] toSkip = null;
if (iMethods != null) {
@@ -1091,6 +1110,7 @@ public void createOTREMethods(RoleModel role) {
private TypeVariableBinding[] createTypeVariables(SignatureWrapper wrapper, boolean assignVariables, char[][][] missingTypeNames,
TypeAnnotationWalker walker, boolean isClassTypeParameter)
{
+ if (this != this.prototype) throw new IllegalStateException();
// detect all type variables first
char[] typeSignature = wrapper.signature;
int depth = 0, length = typeSignature.length;
@@ -1135,7 +1155,7 @@ private TypeVariableBinding[] createTypeVariables(SignatureWrapper wrapper, bool
if (assignVariables)
this.typeVariables = result;
for (int i = 0; i < rank; i++) {
- initializeTypeVariable(result[i], result, wrapper, missingTypeNames, walker.toTypeBarameterBounds(isClassTypeParameter, i));
+ initializeTypeVariable(result[i], result, wrapper, missingTypeNames, walker.toTypeParameterBounds(isClassTypeParameter, i));
}
return result;
}
@@ -1144,8 +1164,7 @@ private TypeVariableBinding[] createTypeVariables(SignatureWrapper wrapper, bool
*
* NOTE: enclosingType of a binary type is resolved when needed
*/
-public ReferenceBinding enclosingType() {
-
+public ReferenceBinding enclosingType() { // should not delegate to prototype.
if ((this.tagBits & TagBits.HasUnresolvedEnclosingType) == 0)
return this.enclosingType;
@@ -1157,8 +1176,13 @@ public ReferenceBinding enclosingType() {
// NOTE: the type of each field of a binary type is resolved when needed
public FieldBinding[] fields() {
- if (this != this.prototype)
- return this.prototype.fields();
+ if (this != this.prototype) {
+ if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
+ return this.fields;
+ this.fields = this.prototype.fields();
+ this.tagBits |= TagBits.AreFieldsComplete;
+ return this.fields;
+ }
if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
return this.fields;
@@ -1177,6 +1201,7 @@ public FieldBinding[] fields() {
}
private MethodBinding findMethod(char[] methodDescriptor, char[][][] missingTypeNames) {
+ if (this != this.prototype) throw new IllegalStateException();
int index = -1;
while (methodDescriptor[++index] != Util.C_PARAM_START) {
// empty
@@ -1368,12 +1393,14 @@ public FieldBinding getField(char[] fieldName, boolean needResolve) {
return needResolve && field != null ? resolveTypeFor(field) : field;
}
/**
- * Rewrite of default getMemberType to avoid resolving eagerly all member types when one is requested
+ * Rewrite of default memberTypes() to avoid resolving eagerly all member types when one is requested
*/
public ReferenceBinding getMemberType(char[] typeName) {
- if (this != this.prototype)
- return this.prototype.getMemberType(typeName);
+ if (this != this.prototype) {
+ ReferenceBinding memberType = this.prototype.getMemberType(typeName);
+ return memberType == null ? null : this.environment.createMemberType(memberType, this);
+ }
for (int i = this.memberTypes.length; --i >= 0;) {
ReferenceBinding memberType = this.memberTypes[i];
@@ -1507,8 +1534,6 @@ public MethodBinding[] getMethods(char[] selector, int suggestedParameterLength)
return Binding.NO_METHODS;
}
public boolean hasMemberTypes() {
- if (this != this.prototype)
- return this.prototype.hasMemberTypes();
return this.memberTypes.length > 0;
}
// NOTE: member types of binary types are resolved when needed
@@ -1537,6 +1562,7 @@ public boolean hasTypeBit(int bit) {
return (this.typeBits & bit) != 0;
}
private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBinding[] existingVariables, SignatureWrapper wrapper, char[][][] missingTypeNames, TypeAnnotationWalker walker) {
+ if (this != this.prototype) throw new IllegalStateException();
// ParameterSignature = Identifier ':' TypeSignature
// or Identifier ':' TypeSignature(optional) InterfaceBound(s)
// InterfaceBound = ':' TypeSignature
@@ -1559,7 +1585,7 @@ private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBi
// variable is visible to its bounds
variable.modifiers |= ExtraCompilerModifiers.AccUnresolved;
- variable.superclass = type;
+ variable.setSuperClass(type);
ReferenceBinding[] bounds = null;
if (wrapper.signature[wrapper.start] == Util.C_COLON) {
@@ -1572,11 +1598,11 @@ private void initializeTypeVariable(TypeVariableBinding variable, TypeVariableBi
types.toArray(bounds);
}
- variable.superInterfaces = bounds == null ? Binding.NO_SUPERINTERFACES : bounds;
+ variable.setSuperInterfaces(bounds == null ? Binding.NO_SUPERINTERFACES : bounds);
if (firstBound == null) {
firstBound = variable.superInterfaces.length == 0 ? null : variable.superInterfaces[0];
}
- variable.firstBound = firstBound;
+ variable.setFirstBound(firstBound);
}
/**
* Returns true if a type is identical to another one,
@@ -1617,6 +1643,10 @@ public boolean isHierarchyConnected() {
return (this.tagBits & (TagBits.HasUnresolvedSuperclass | TagBits.HasUnresolvedSuperinterfaces)) == 0;
}
+public boolean isRepeatableAnnotation() {
+ if (this != this.prototype) throw new IllegalStateException();
+ return this.containingAnnotation != null;
+}
public int kind() {
if (this != this.prototype)
@@ -1628,9 +1658,19 @@ public int kind() {
}
// NOTE: member types of binary types are resolved when needed
public ReferenceBinding[] memberTypes() {
-
- if (this != this.prototype)
- return this.prototype.memberTypes();
+ if (this != this.prototype) {
+ if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0)
+ return this.memberTypes;
+ ReferenceBinding [] members = this.prototype.memberTypes();
+ int memberTypesLength = members == null ? 0 : members.length;
+ if (memberTypesLength > 0) {
+ this.memberTypes = new ReferenceBinding[memberTypesLength];
+ for (int i = 0; i < memberTypesLength; i++)
+ this.memberTypes[i] = this.environment.createMemberType(members[i], this);
+ }
+ this.tagBits &= ~TagBits.HasUnresolvedMemberTypes;
+ return this.memberTypes;
+ }
if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0)
return this.memberTypes;
@@ -1643,8 +1683,13 @@ public ReferenceBinding[] memberTypes() {
// NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
public MethodBinding[] methods() {
- if (this != this.prototype)
- return this.prototype.methods();
+ if (this != this.prototype) {
+ if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
+ return this.methods;
+ this.methods = this.prototype.methods();
+ this.tagBits |= TagBits.AreMethodsComplete;
+ return this.methods;
+ }
if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
return this.methods;
@@ -1661,6 +1706,19 @@ public MethodBinding[] methods() {
this.tagBits |= TagBits.AreMethodsComplete;
return this.methods;
}
+
+public TypeBinding prototype() {
+ return this.prototype;
+}
+
+public ReferenceBinding resolveContainerAnnotation() {
+ if (this != this.prototype) throw new IllegalStateException();
+ if (this.containingAnnotation instanceof UnresolvedReferenceBinding) {
+ this.containingAnnotation = (ReferenceBinding) BinaryTypeBinding.resolveType(this.containingAnnotation, this.environment, false);
+ }
+ return this.containingAnnotation;
+}
+
private FieldBinding resolveTypeFor(FieldBinding field) {
if (this != this.prototype)
@@ -1753,6 +1811,10 @@ AnnotationBinding[] retrieveAnnotations(Binding binding) {
return AnnotationBinding.addStandardAnnotations(super.retrieveAnnotations(binding), binding.getAnnotationTagBits(), this.environment);
}
+public void setContainingAnnotation(ReferenceBinding value) {
+ if (this != this.prototype) throw new IllegalStateException();
+ this.containingAnnotation = value;
+}
SimpleLookupTable storedAnnotations(boolean forceInitialize) {
if (this != this.prototype)
@@ -1770,6 +1832,18 @@ SimpleLookupTable storedAnnotations(boolean forceInitialize) {
}
private void scanFieldForNullAnnotation(IBinaryField field, FieldBinding fieldBinding) {
+ if (this != this.prototype) throw new IllegalStateException();
+ if (this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8) {
+ TypeBinding fieldType = fieldBinding.type;
+ if (fieldType != null
+ && !fieldType.isBaseType()
+ && (fieldType.tagBits & TagBits.AnnotationNullMASK) == 0
+ && (this.tagBits & TagBits.AnnotationNonNullByDefault) != 0) {
+ fieldBinding.type = this.environment.createAnnotatedType(fieldType, new AnnotationBinding[]{this.environment.getNonNullAnnotation()});
+ }
+ return; // not using fieldBinding.tagBits when we have type annotations.
+ }
+
// global option is checked by caller
char[][] nullableAnnotationName = this.environment.getNullableAnnotationName();
char[][] nonNullAnnotationName = this.environment.getNonNullAnnotationName();
@@ -1805,6 +1879,7 @@ private void scanFieldForNullAnnotation(IBinaryField field, FieldBinding fieldBi
}
private void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding methodBinding) {
+ if (this != this.prototype) throw new IllegalStateException();
if (!this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled)
return;
boolean useTypeAnnotations = this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8;
@@ -1827,12 +1902,11 @@ private void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding met
if (CharOperation.equals(typeName, nonNullByDefaultAnnotationName)) {
methodBinding.tagBits |= TagBits.AnnotationNonNullByDefault;
}
- if (!useTypeAnnotations) {
- if (!explicitNullness && CharOperation.equals(typeName, nonNullAnnotationName)) {
+ if (!useTypeAnnotations && !explicitNullness) {
+ if (CharOperation.equals(typeName, nonNullAnnotationName)) {
methodBinding.tagBits |= TagBits.AnnotationNonNull;
explicitNullness = true;
- }
- if (!explicitNullness && CharOperation.equals(typeName, nullableAnnotationName)) {
+ } else if (CharOperation.equals(typeName, nullableAnnotationName)) {
methodBinding.tagBits |= TagBits.AnnotationNullable;
explicitNullness = true;
}
@@ -1876,6 +1950,7 @@ private void scanMethodForNullAnnotation(IBinaryMethod method, MethodBinding met
}
}
private void scanTypeForNullDefaultAnnotation(IBinaryType binaryType, PackageBinding packageBinding, BinaryTypeBinding binaryBinding) {
+ if (this != this.prototype) throw new IllegalStateException();
char[][] nonNullByDefaultAnnotationName = this.environment.getNonNullByDefaultAnnotationName();
if (nonNullByDefaultAnnotationName == null)
return; // not well-configured to use null annotations
@@ -1951,14 +2026,40 @@ private void scanTypeForNullDefaultAnnotation(IBinaryType binaryType, PackageBin
}
}
+private void scanTypeForContainerAnnotation(IBinaryType binaryType, char[][][] missingTypeNames) {
+ if (this != this.prototype) throw new IllegalStateException();
+ IBinaryAnnotation[] annotations = binaryType.getAnnotations();
+ if (annotations != null) {
+ int length = annotations.length;
+ for (int i = 0; i < length; i++) {
+ char[] annotationTypeName = annotations[i].getTypeName();
+ if (CharOperation.equals(annotationTypeName, ConstantPool.JAVA_LANG_ANNOTATION_REPEATABLE)) {
+ IBinaryElementValuePair[] elementValuePairs = annotations[i].getElementValuePairs();
+ if (elementValuePairs != null && elementValuePairs.length == 1) {
+ Object value = elementValuePairs[0].getValue();
+ if (value instanceof ClassSignature) {
+ this.containingAnnotation = (ReferenceBinding) this.environment.getTypeFromSignature(((ClassSignature)value).getTypeName(), 0, -1, false, null, missingTypeNames, TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
/* Answer the receiver's superclass... null if the receiver is Object or an interface.
*
* NOTE: superclass of a binary type is resolved when needed
*/
public ReferenceBinding superclass() {
- if (this != this.prototype)
- return this.prototype.superclass();
+ if (this != this.prototype) {
+ if ((this.tagBits & TagBits.HasUnresolvedSuperclass) == 0)
+ return this.superclass;
+ this.superclass = this.prototype.superclass();
+ this.tagBits &= ~TagBits.HasUnresolvedSuperclass;
+ return this.superclass;
+ }
if ((this.tagBits & TagBits.HasUnresolvedSuperclass) == 0)
return this.superclass;
@@ -2004,9 +2105,13 @@ public void resetSuperclass(ReferenceBinding superClass) {
// NOTE: superInterfaces of binary types are resolved when needed
public ReferenceBinding[] superInterfaces() {
- if (this != this.prototype)
- return this.prototype.superInterfaces();
-
+ if (this != this.prototype) {
+ if ((this.tagBits & TagBits.HasUnresolvedSuperinterfaces) == 0)
+ return this.superInterfaces;
+ this.superInterfaces = this.prototype.superInterfaces();
+ this.tagBits &= ~TagBits.HasUnresolvedSuperinterfaces;
+ return this.superInterfaces;
+ }
if ((this.tagBits & TagBits.HasUnresolvedSuperinterfaces) == 0)
return this.superInterfaces;
@@ -2032,9 +2137,13 @@ public ReferenceBinding[] superInterfaces() {
}
public TypeVariableBinding[] typeVariables() {
- if (this != this.prototype)
- return this.prototype.typeVariables();
-
+ if (this != this.prototype) {
+ if ((this.tagBits & TagBits.HasUnresolvedTypeVariables) == 0)
+ return this.typeVariables;
+ this.typeVariables = this.prototype.typeVariables();
+ this.tagBits &= ~TagBits.HasUnresolvedTypeVariables;
+ return this.typeVariables;
+ }
if ((this.tagBits & TagBits.HasUnresolvedTypeVariables) == 0)
return this.typeVariables;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
index ecb74a11b..56b0e8596 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java
@@ -109,6 +109,8 @@ public abstract class Binding {
/**
* Compute the tagbits for standard annotations. For source types, these could require
* lazily resolving corresponding annotation nodes, in case of forward references.
+ * For type use bindings, this method still returns the tagbits corresponding to the type
+ * declaration binding.
* @see org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding#getAnnotationTagBits()
*/
public long getAnnotationTagBits() {
@@ -124,6 +126,10 @@ public abstract class Binding {
// empty block
}
+ public boolean isAnnotationType() {
+ return false;
+ }
+
/* API
* Answer true if the receiver is not a problem binding
*/
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java
index 913ca61b2..b63d85188 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java
@@ -34,18 +34,29 @@ public class CaptureBinding extends TypeVariableBinding {
public CaptureBinding(WildcardBinding wildcard, ReferenceBinding sourceType, int position, int captureID) {
super(TypeConstants.WILDCARD_CAPTURE_NAME_PREFIX, null, 0, wildcard.environment);
- // Capture the unannotated wildcard and then capture the annotations.
- if (wildcard.hasTypeAnnotations()) {
- this.wildcard = (WildcardBinding) wildcard.unannotated();
- setTypeAnnotations(wildcard.getTypeAnnotations(), wildcard.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled);
- } else {
- this.wildcard = wildcard;
- }
+ this.wildcard = wildcard;
this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; // treat capture as public
this.fPackage = wildcard.fPackage;
this.sourceType = sourceType;
this.position = position;
this.captureID = captureID;
+ if (wildcard.hasTypeAnnotations()) {
+ setTypeAnnotations(wildcard.getTypeAnnotations(), wildcard.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled);
+ }
+ }
+
+ public CaptureBinding(CaptureBinding prototype) {
+ super(prototype);
+ this.wildcard = prototype.wildcard;
+ this.sourceType = prototype.sourceType;
+ this.position = prototype.position;
+ this.captureID = prototype.captureID;
+ this.lowerBound = prototype.lowerBound;
+ }
+
+ // Captures may get cloned and annotated during type inference.
+ public TypeBinding clone(TypeBinding enclosingType) {
+ return new CaptureBinding(this);
}
/*
@@ -110,30 +121,30 @@ public class CaptureBinding extends TypeVariableBinding {
// still need to capture bound supertype as well so as not to expose wildcards to the outside (111208)
TypeBinding capturedWildcardBound = originalWildcardBound.capture(scope, this.position);
if (originalWildcardBound.isInterface()) {
- this.superclass = scope.getJavaLangObject();
- this.superInterfaces = new ReferenceBinding[] { (ReferenceBinding) capturedWildcardBound };
+ this.setSuperClass(scope.getJavaLangObject());
+ this.setSuperInterfaces(new ReferenceBinding[] { (ReferenceBinding) capturedWildcardBound });
} else {
// the wildcard bound should be a subtype of variable superclass
// it may occur that the bound is less specific, then consider glb (202404)
if (capturedWildcardBound.isArrayType() || capturedWildcardBound == this) {
- this.superclass = scope.getJavaLangObject();
+ this.setSuperClass(scope.getJavaLangObject());
} else {
- this.superclass = (ReferenceBinding) capturedWildcardBound;
+ this.setSuperClass((ReferenceBinding) capturedWildcardBound);
}
- this.superInterfaces = Binding.NO_SUPERINTERFACES;
+ this.setSuperInterfaces(Binding.NO_SUPERINTERFACES);
}
- this.firstBound = capturedWildcardBound;
+ this.setFirstBound(capturedWildcardBound);
if ((capturedWildcardBound.tagBits & TagBits.HasTypeVariable) == 0)
this.tagBits &= ~TagBits.HasTypeVariable;
break;
case Wildcard.UNBOUND :
- this.superclass = scope.getJavaLangObject();
- this.superInterfaces = Binding.NO_SUPERINTERFACES;
+ this.setSuperClass(scope.getJavaLangObject());
+ this.setSuperInterfaces(Binding.NO_SUPERINTERFACES);
this.tagBits &= ~TagBits.HasTypeVariable;
break;
case Wildcard.SUPER :
- this.superclass = scope.getJavaLangObject();
- this.superInterfaces = Binding.NO_SUPERINTERFACES;
+ this.setSuperClass(scope.getJavaLangObject());
+ this.setSuperInterfaces(Binding.NO_SUPERINTERFACES);
this.lowerBound = this.wildcard.bound;
if ((originalWildcardBound.tagBits & TagBits.HasTypeVariable) == 0)
this.tagBits &= ~TagBits.HasTypeVariable;
@@ -166,44 +177,44 @@ public class CaptureBinding extends TypeVariableBinding {
capturedWildcardBound = RoleTypeCreator.maybeWrapUnqualifiedRoleType(scope, capturedWildcardBound.enclosingType(), capturedWildcardBound, scope.methodScope().referenceMethod(), scope.problemReporter());
// SH}
if (originalWildcardBound.isInterface()) {
- this.superclass = substitutedVariableSuperclass;
+ this.setSuperClass(substitutedVariableSuperclass);
// merge wildcard bound into variable superinterfaces using glb
if (substitutedVariableInterfaces == Binding.NO_SUPERINTERFACES) {
- this.superInterfaces = new ReferenceBinding[] { (ReferenceBinding) capturedWildcardBound };
+ this.setSuperInterfaces(new ReferenceBinding[] { (ReferenceBinding) capturedWildcardBound });
} else {
int length = substitutedVariableInterfaces.length;
System.arraycopy(substitutedVariableInterfaces, 0, substitutedVariableInterfaces = new ReferenceBinding[length+1], 1, length);
substitutedVariableInterfaces[0] = (ReferenceBinding) capturedWildcardBound;
- this.superInterfaces = Scope.greaterLowerBound(substitutedVariableInterfaces);
+ this.setSuperInterfaces(Scope.greaterLowerBound(substitutedVariableInterfaces));
}
} else {
// the wildcard bound should be a subtype of variable superclass
// it may occur that the bound is less specific, then consider glb (202404)
if (capturedWildcardBound.isArrayType() || capturedWildcardBound == this) {
- this.superclass = substitutedVariableSuperclass;
+ this.setSuperClass(substitutedVariableSuperclass);
} else {
- this.superclass = (ReferenceBinding) capturedWildcardBound;
+ this.setSuperClass((ReferenceBinding) capturedWildcardBound);
if (this.superclass.isSuperclassOf(substitutedVariableSuperclass)) {
- this.superclass = substitutedVariableSuperclass;
+ this.setSuperClass(substitutedVariableSuperclass);
}
}
- this.superInterfaces = substitutedVariableInterfaces;
+ this.setSuperInterfaces(substitutedVariableInterfaces);
}
- this.firstBound = capturedWildcardBound;
+ this.setFirstBound(capturedWildcardBound);
if ((capturedWildcardBound.tagBits & TagBits.HasTypeVariable) == 0)
this.tagBits &= ~TagBits.HasTypeVariable;
break;
case Wildcard.UNBOUND :
- this.superclass = substitutedVariableSuperclass;
- this.superInterfaces = substitutedVariableInterfaces;
+ this.setSuperClass(substitutedVariableSuperclass);
+ this.setSuperInterfaces(substitutedVariableInterfaces);
this.tagBits &= ~TagBits.HasTypeVariable;
break;
case Wildcard.SUPER :
- this.superclass = substitutedVariableSuperclass;
+ this.setSuperClass(substitutedVariableSuperclass);
if (wildcardVariable.firstBound == substitutedVariableSuperclass || originalWildcardBound == substitutedVariableSuperclass) {
- this.firstBound = substitutedVariableSuperclass;
+ this.setFirstBound(substitutedVariableSuperclass);
}
- this.superInterfaces = substitutedVariableInterfaces;
+ this.setSuperInterfaces(substitutedVariableInterfaces);
this.lowerBound = originalWildcardBound;
if ((originalWildcardBound.tagBits & TagBits.HasTypeVariable) == 0)
this.tagBits &= ~TagBits.HasTypeVariable;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index be686c2bf..fe74e5c2a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 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
@@ -22,6 +22,8 @@
* Bug 395977 - [compiler][resource] Resource leak warning behavior possibly incorrect for anonymous inner class
* Bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
* Bug 416176 - [1.8][compiler][null] null type annotations cause grief on type variables
+ * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
+ * Bug 415821 - [1.8][compiler] CLASS_EXTENDS target type annotation missing for anonymous classes
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -171,33 +173,35 @@ public class ClassScope extends Scope {
}
anonymousType.typeBits |= inheritedBits;
if (supertype.isInterface()) {
- anonymousType.superclass = getJavaLangObject();
- anonymousType.superInterfaces = new ReferenceBinding[] { supertype };
+ anonymousType.setSuperClass(getJavaLangObject());
+ anonymousType.setSuperInterfaces(new ReferenceBinding[] { supertype });
TypeReference typeReference = this.referenceContext.allocation.type;
if (typeReference != null) {
+ this.referenceContext.superInterfaces = new TypeReference[] { typeReference };
if ((supertype.tagBits & TagBits.HasDirectWildcard) != 0) {
problemReporter().superTypeCannotUseWildcard(anonymousType, typeReference, supertype);
anonymousType.tagBits |= TagBits.HierarchyHasProblems;
- anonymousType.superInterfaces = Binding.NO_SUPERINTERFACES;
+ anonymousType.setSuperInterfaces(Binding.NO_SUPERINTERFACES);
}
}
} else {
- anonymousType.superclass = supertype;
- anonymousType.superInterfaces = Binding.NO_SUPERINTERFACES;
+ anonymousType.setSuperClass(supertype);
+ anonymousType.setSuperInterfaces(Binding.NO_SUPERINTERFACES);
TypeReference typeReference = this.referenceContext.allocation.type;
if (typeReference != null) { // no check for enum constant body
+ this.referenceContext.superclass = typeReference;
if (supertype.erasure().id == TypeIds.T_JavaLangEnum) {
problemReporter().cannotExtendEnum(anonymousType, typeReference, supertype);
anonymousType.tagBits |= TagBits.HierarchyHasProblems;
- anonymousType.superclass = getJavaLangObject();
+ anonymousType.setSuperClass(getJavaLangObject());
} else if (supertype.isFinal()) {
problemReporter().anonymousClassCannotExtendFinalClass(typeReference, supertype);
anonymousType.tagBits |= TagBits.HierarchyHasProblems;
- anonymousType.superclass = getJavaLangObject();
+ anonymousType.setSuperClass(getJavaLangObject());
} else if ((supertype.tagBits & TagBits.HasDirectWildcard) != 0) {
problemReporter().superTypeCannotUseWildcard(anonymousType, typeReference, supertype);
anonymousType.tagBits |= TagBits.HierarchyHasProblems;
- anonymousType.superclass = getJavaLangObject();
+ anonymousType.setSuperClass(getJavaLangObject());
}
}
}
@@ -420,7 +424,7 @@ public class ClassScope extends Scope {
if (count != size)
System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
}
- localType.memberTypes = memberTypeBindings;
+ localType.setMemberTypes(memberTypeBindings);
return localType;
}
@@ -507,7 +511,7 @@ public class ClassScope extends Scope {
if (count != length)
System.arraycopy(memberTypeBindings, 0, memberTypeBindings = new ReferenceBinding[count], 0, count);
}
- sourceType.memberTypes = memberTypeBindings;
+ sourceType.setMemberTypes(memberTypeBindings);
}
void buildMethods() {
@@ -712,10 +716,10 @@ public class ClassScope extends Scope {
TypeParameter[] typeParameters = this.referenceContext.typeParameters;
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850, If they exist at all, process type parameters irrespective of source level.
if (typeParameters == null || typeParameters.length == 0) {
- sourceType.typeVariables = Binding.NO_TYPE_VARIABLES;
+ sourceType.setTypeVariables(Binding.NO_TYPE_VARIABLES);
return;
}
- sourceType.typeVariables = Binding.NO_TYPE_VARIABLES; // safety
+ sourceType.setTypeVariables(Binding.NO_TYPE_VARIABLES); // safety
if (sourceType.id == TypeIds.T_JavaLangObject) { // handle the case of redefining java.lang.Object up front
problemReporter().objectCannotBeGeneric(this.referenceContext);
@@ -726,7 +730,7 @@ public class ClassScope extends Scope {
if (typeParameters.length == 0)
return; // consumed all parameters
// SH}
- sourceType.typeVariables = createTypeVariables(typeParameters, sourceType);
+ sourceType.setTypeVariables(createTypeVariables(typeParameters, sourceType));
sourceType.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
}
@@ -1542,8 +1546,8 @@ public class ClassScope extends Scope {
return connectSuperteam();
// SH}
if (sourceType.id == TypeIds.T_JavaLangObject) { // handle the case of redefining java.lang.Object up front
- sourceType.superclass = null;
- sourceType.superInterfaces = Binding.NO_SUPERINTERFACES;
+ sourceType.setSuperClass(null);
+ sourceType.setSuperInterfaces(Binding.NO_SUPERINTERFACES);
if (!sourceType.isClass())
problemReporter().objectMustBeClass(sourceType);
if (this.referenceContext.superclass != null || (this.referenceContext.superInterfaces != null && this.referenceContext.superInterfaces.length > 0))
@@ -1557,7 +1561,7 @@ public class ClassScope extends Scope {
// SH}
if (sourceType.isEnum() && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) // do not connect if source < 1.5 as enum already got flagged as syntax error
return connectEnumSuperclass();
- sourceType.superclass = getJavaLangObject();
+ sourceType.setSuperClass(getJavaLangObject());
return !detectHierarchyCycle(sourceType, sourceType.superclass, null);
}
TypeReference superclassRef = this.referenceContext.superclass;
@@ -1592,7 +1596,7 @@ public class ClassScope extends Scope {
problemReporter().cannotExtendEnum(sourceType, superclassRef, superclass);
} else if ((superclass.tagBits & TagBits.HierarchyHasProblems) != 0
|| !superclassRef.resolvedType.isValidBinding()) {
- sourceType.superclass = superclass;
+ sourceType.setSuperClass(superclass);
sourceType.tagBits |= TagBits.HierarchyHasProblems; // propagate if missing supertype
return superclassRef.resolvedType.isValidBinding(); // reported some error against the source type ?
//{ObjectTeams: team super class only allowed for teams
@@ -1603,7 +1607,7 @@ public class ClassScope extends Scope {
// SH}
} else {
// only want to reach here when no errors are reported
- sourceType.superclass = superclass;
+ sourceType.setSuperClass(superclass);
sourceType.typeBits |= (superclass.typeBits & TypeIds.InheritableBits);
// further analysis against white lists for the unlikely case we are compiling java.io.*:
if ((sourceType.typeBits & (TypeIds.BitAutoCloseable|TypeIds.BitCloseable)) != 0)
@@ -1612,7 +1616,7 @@ public class ClassScope extends Scope {
}
}
sourceType.tagBits |= TagBits.HierarchyHasProblems;
- sourceType.superclass = getJavaLangObject();
+ sourceType.setSuperClass(getJavaLangObject());
if ((sourceType.superclass.tagBits & TagBits.BeginHierarchyCheck) == 0)
detectHierarchyCycle(sourceType, sourceType.superclass, null);
return false; // reported some error against the source type
@@ -1626,7 +1630,7 @@ public class ClassScope extends Scope {
ReferenceBinding rootEnumType = getJavaLangEnum();
if ((rootEnumType.tagBits & TagBits.HasMissingType) != 0) {
sourceType.tagBits |= TagBits.HierarchyHasProblems; // mark missing supertpye
- sourceType.superclass = rootEnumType;
+ sourceType.setSuperClass(rootEnumType);
return false;
}
boolean foundCycle = detectHierarchyCycle(sourceType, rootEnumType, null);
@@ -1647,7 +1651,7 @@ public class ClassScope extends Scope {
} ,
null);
sourceType.tagBits |= (superType.tagBits & TagBits.HierarchyHasProblems); // propagate if missing supertpye
- sourceType.superclass = superType;
+ sourceType.setSuperClass(superType);
// bound check (in case of bogus definition of Enum type)
if (refTypeVariables[0].boundCheck(superType, sourceType, this) != TypeConstants.OK) {
problemReporter().typeMismatchError(rootEnumType, refTypeVariables[0], sourceType, null);
@@ -2021,12 +2025,12 @@ public class ClassScope extends Scope {
*/
private boolean connectSuperInterfaces() {
SourceTypeBinding sourceType = this.referenceContext.binding;
- sourceType.superInterfaces = Binding.NO_SUPERINTERFACES;
+ sourceType.setSuperInterfaces(Binding.NO_SUPERINTERFACES);
if (this.referenceContext.superInterfaces == null) {
if (sourceType.isAnnotationType() && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) { // do not connect if source < 1.5 as annotation already got flagged as syntax error) {
ReferenceBinding annotationType = getJavaLangAnnotationAnnotation();
boolean foundCycle = detectHierarchyCycle(sourceType, annotationType, null);
- sourceType.superInterfaces = new ReferenceBinding[] { annotationType };
+ sourceType.setSuperInterfaces(new ReferenceBinding[] { annotationType });
return !foundCycle;
}
return true;
@@ -2097,7 +2101,7 @@ public class ClassScope extends Scope {
if (count > 0) {
if (count != length)
System.arraycopy(interfaceBindings, 0, interfaceBindings = new ReferenceBinding[count], 0, count);
- sourceType.superInterfaces = interfaceBindings;
+ sourceType.setSuperInterfaces(interfaceBindings);
}
return noProblems;
}
@@ -2370,7 +2374,7 @@ public class ClassScope extends Scope {
return superType;
} catch (AbortCompilation e) {
SourceTypeBinding sourceType = this.referenceContext.binding;
- if (sourceType.superInterfaces == null) sourceType.superInterfaces = Binding.NO_SUPERINTERFACES; // be more resilient for hierarchies (144976)
+ if (sourceType.superInterfaces == null) sourceType.setSuperInterfaces(Binding.NO_SUPERINTERFACES); // be more resilient for hierarchies (144976)
e.updateContext(typeReference, referenceCompilationUnit().compilationResult);
throw e;
} finally {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
index 2afd2b693..bfd619539 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
@@ -4,7 +4,10 @@
* 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
- * $Id: FieldBinding.java 23405 2010-02-03 17:02:18Z stephan $
+ *
+ * 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
@@ -13,6 +16,7 @@
* Stephan Herrmann <stephan@cs.tu-berlin.de> - Contributions for
* bug 185682 - Increment/decrement operators mark local variables as read
* bug 331649 - [compiler][null] consider null annotations for fields
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -136,7 +140,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
if (isPublic()) return true;
SourceTypeBinding invocationType = scope.enclosingSourceType();
- if (invocationType == this.declaringClass && invocationType == receiverType) return true;
+ if (TypeBinding.equalsEquals(invocationType, this.declaringClass) && TypeBinding.equalsEquals(invocationType, receiverType)) return true;
if (invocationType == null) // static import call
return !isPrivate() && scope.getCurrentPackage() == this.declaringClass.fPackage;
@@ -152,7 +156,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
// AND the receiverType is the invocationType or its subclass
// OR the method is a static method accessed directly through a type
// OR previous assertions are true for one of the enclosing type
- if (invocationType == this.declaringClass) return true;
+ if (TypeBinding.equalsEquals(invocationType, this.declaringClass)) return true;
if (invocationType.fPackage == this.declaringClass.fPackage) return true;
ReferenceBinding currentType = invocationType;
@@ -170,7 +174,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
if (depth > 0) invocationSite.setDepth(depth);
return true; // see 1FMEPDL - return invocationSite.isTypeAccess();
}
- if (currentType == receiverErasure || receiverErasure.findSuperTypeOriginatingFrom(currentType) != null) {
+ if (TypeBinding.equalsEquals(currentType, receiverErasure) || receiverErasure.findSuperTypeOriginatingFrom(currentType) != null) {
if (depth > 0) invocationSite.setDepth(depth);
return true;
}
@@ -185,7 +189,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
// answer true if the receiverType is the declaringClass
// AND the invocationType and the declaringClass have a common enclosingType
receiverCheck: {
- if (receiverType != this.declaringClass) {
+ if (TypeBinding.notEquals(receiverType, this.declaringClass)) {
// special tolerance for type variable direct bounds, but only if compliance <= 1.6, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=334622
if (scope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_6 && receiverType.isTypeVariable() && ((TypeVariableBinding) receiverType).isErasureBoundTo(this.declaringClass.erasure()))
break receiverCheck;
@@ -193,7 +197,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
}
}
- if (invocationType != this.declaringClass) {
+ if (TypeBinding.notEquals(invocationType, this.declaringClass)) {
ReferenceBinding outerInvocationType = invocationType;
ReferenceBinding temp = outerInvocationType.enclosingType();
while (temp != null) {
@@ -207,7 +211,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
outerDeclaringClass = temp;
temp = temp.enclosingType();
}
- if (outerInvocationType != outerDeclaringClass) return false;
+ if (TypeBinding.notEquals(outerInvocationType, outerDeclaringClass)) return false;
}
return true;
}
@@ -223,9 +227,9 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
ReferenceBinding currentType = (ReferenceBinding) receiverType;
do {
if (currentType.isCapture()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=285002
- if (originalDeclaringClass == currentType.erasure().original()) return true;
+ if (TypeBinding.equalsEquals(originalDeclaringClass, currentType.erasure().original())) return true;
} else {
- if (originalDeclaringClass == currentType.original()) return true;
+ if (TypeBinding.equalsEquals(originalDeclaringClass, currentType.original())) return true;
}
PackageBinding currentPackage = currentType.fPackage;
// package could be null for wildcards/intersection types, ignore and recurse in superclass
@@ -302,11 +306,15 @@ public Constant constant() {
}
public void fillInDefaultNonNullness(FieldDeclaration sourceField, Scope scope) {
+ LookupEnvironment environment = scope.environment();
if ( this.type != null
&& !this.type.isBaseType()
- && (this.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) == 0)
+ && (this.tagBits & TagBits.AnnotationNullMASK) == 0)
{
- this.tagBits |= TagBits.AnnotationNonNull;
+ if (environment.globalOptions.sourceLevel < ClassFileConstants.JDK1_8)
+ this.tagBits |= TagBits.AnnotationNonNull;
+ else
+ this.type = environment.createAnnotatedType(this.type, new AnnotationBinding[]{environment.getNonNullAnnotation()});
} else if ((this.tagBits & TagBits.AnnotationNonNull) != 0) {
scope.problemReporter().nullAnnotationIsRedundant(sourceField);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java
index 8a506c422..feffe9d61 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ImplicitNullAnnotationVerifier.java
@@ -23,6 +23,7 @@ import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBinding;
@@ -52,9 +53,10 @@ public class ImplicitNullAnnotationVerifier {
// can be 'this', but is never a MethodVerifier (to avoid infinite recursion).
ImplicitNullAnnotationVerifier buddyImplicitNullAnnotationsVerifier;
private boolean inheritNullAnnotations;
+
+//{ObjectTeams: added field and 2nd ctor arg:
private LookupEnvironment environment;
-//{ObjectTeams: added 2nd arg:
public ImplicitNullAnnotationVerifier(boolean inheritNullAnnotations, LookupEnvironment environment) {
this.environment = environment;
// SH}
@@ -137,9 +139,8 @@ public class ImplicitNullAnnotationVerifier {
currentMethod.tagBits |= tagBits;
} else {
if (!currentMethod.returnType.isBaseType()) {
- // TODO(Stephan: Synthesize AnnotationBinding[] and call LE#createAnnotatedType(TB, AB[]);
- // currentMethod.returnType = scope.environment()
- // .createAnnotatedType(currentMethod.returnType, tagBits);
+ LookupEnvironment env = scope.environment();
+ currentMethod.returnType = env.createAnnotatedType(currentMethod.returnType, env.nullAnnotationsFromTagBits(tagBits));
}
}
}
@@ -401,8 +402,7 @@ public class ImplicitNullAnnotationVerifier {
method.tagBits |= nullnessBits;
} else {
if (!method.returnType.isBaseType()) {
- // TODO(Stephan: Synthesize AnnotationBinding[] and call LE#createAnnotatedType(TB, AB[]);
- // method.returnType = environment.createAnnotatedType(method.returnType, nullnessBits);
+ method.returnType = environment.createAnnotatedType(method.returnType, environment.nullAnnotationsFromTagBits(nullnessBits));
}
}
}
@@ -411,7 +411,7 @@ public class ImplicitNullAnnotationVerifier {
if (useTypeAnnotations) {
TypeBinding parameter = method.parameters[i];
if (parameter != null) {
- long nullBits = parameter.tagBits & TagBits.AnnotationNullMASK;
+ long nullBits = NullAnnotationMatching.validNullTagBits(parameter.tagBits);
if (nullBits != 0L)
return Boolean.valueOf(nullBits == TagBits.AnnotationNonNull);
}
@@ -425,7 +425,7 @@ public class ImplicitNullAnnotationVerifier {
if (useTypeAnnotations) {
if (method.returnType == null)
return 0L;
- return method.returnType.tagBits & TagBits.AnnotationNullMASK;
+ return NullAnnotationMatching.validNullTagBits(method.returnType.tagBits);
}
return method.tagBits & TagBits.AnnotationNullMASK;
}
@@ -458,9 +458,8 @@ public class ImplicitNullAnnotationVerifier {
}
}
void recordArgNonNullness18(MethodBinding method, int paramIdx, Argument currentArgument, Boolean nonNullNess, LookupEnvironment env) {
- // TODO(Stephan: Synthesize AnnotationBinding[] and call LE#createAnnotatedType(TB, AB[]);
- // method.parameters[paramIdx] = env.createAnnotatedType(method.parameters[paramIdx],
- // nonNullNess.booleanValue() ? TagBits.AnnotationNonNull : TagBits.AnnotationNullable);
+ AnnotationBinding annotationBinding = nonNullNess.booleanValue() ? env.getNonNullAnnotation() : env.getNullableAnnotation();
+ method.parameters[paramIdx] = env.createAnnotatedType(method.parameters[paramIdx], new AnnotationBinding[]{ annotationBinding});
if (currentArgument != null) {
currentArgument.binding.type = method.parameters[paramIdx];
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
index 4f3d236bb..dd1a922f6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalTypeBinding.java
@@ -90,6 +90,7 @@ public LocalTypeBinding(LocalTypeBinding prototype) {
* all its dependents so as to update them (see updateInnerEmulationDependents()).
*/
public void addInnerEmulationDependent(BlockScope dependentScope, boolean wasEnclosingInstanceSupplied) {
+ if (this != this.prototype) throw new IllegalStateException();
int index;
if (this.dependents == null) {
index = 0;
@@ -128,10 +129,9 @@ public ReferenceBinding anonymousOriginalSuperType() {
}
protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation[] annotations, long annotationTagBits) {
- if (this != this.prototype) {
- this.prototype.checkRedundantNullnessDefaultRecurse(location, annotations, annotationTagBits);
- return;
- }
+
+ if (this != this.prototype) throw new IllegalStateException();
+
long outerDefault = this.enclosingMethod != null ? this.enclosingMethod.tagBits & ((TagBits.AnnotationNonNullByDefault|TagBits.AnnotationNullUnspecifiedByDefault)) : 0;
if (outerDefault != 0) {
if (outerDefault == annotationTagBits) {
@@ -175,7 +175,7 @@ public char[] constantPoolName() /* java/lang/Object */ {
if (this.constantPoolName != null)
return this.constantPoolName;
if (this != this.prototype)
- this.prototype.constantPoolName();
+ return this.constantPoolName = this.prototype.constantPoolName();
if (this.constantPoolName == null && this.scope != null) {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=322154, we do have some
// cases where the left hand does not know what the right is doing.
@@ -184,11 +184,9 @@ public char[] constantPoolName() /* java/lang/Object */ {
return this.constantPoolName;
}
-public TypeBinding clone(TypeBinding outerType, TypeBinding[] typeArguments) {
+public TypeBinding clone(TypeBinding outerType) {
LocalTypeBinding copy = new LocalTypeBinding(this);
- if (outerType == null) {
- outerType = enclosingType();
- }
+ copy.enclosingType = (SourceTypeBinding) outerType;
return copy;
}
@@ -264,9 +262,10 @@ public char[] shortReadableName() /*Object*/ {
return shortReadableName;
}
-//Record that the type is a local member type
+// Record that the type is a local member type
public void setAsMemberType() {
if (this != this.prototype) {
+ this.tagBits |= TagBits.MemberTypeMask;
((LocalTypeBinding) this.prototype).setAsMemberType();
return;
}
@@ -275,6 +274,7 @@ public void setAsMemberType() {
public void setConstantPoolName(char[] computedConstantPoolName) /* java/lang/Object */ {
if (this != this.prototype) {
+ this.constantPoolName = computedConstantPoolName;
((LocalTypeBinding) this.prototype).setConstantPoolName(computedConstantPoolName);
return;
}
@@ -332,10 +332,7 @@ public String toString() {
* to be propagated to all dependent source types.
*/
public void updateInnerEmulationDependents() {
- if (this != this.prototype) {
- ((LocalTypeBinding) this.prototype).updateInnerEmulationDependents();
- return;
- }
+ if (this != this.prototype) throw new IllegalStateException();
if (this.dependents != null) {
for (int i = 0; i < this.dependents.length; i++) {
InnerEmulationDependency dependency = this.dependents[i];
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index 2165a379c..652722b7a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -27,6 +27,7 @@
* Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099
* Bug 416183 - [1.8][compiler][null] Overload resolution fails with null annotations
* Bug 416307 - [1.8][compiler][null] subclass with type parameter substitution confuses null checking
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -114,7 +115,7 @@ public class LookupEnvironment implements ProblemReasons, TypeConstants {
private int lastCompletedUnitIndex = -1;
private int lastUnitIndex = -1;
- private AnnotatableTypeSystem typeSystem;
+ private TypeSystem typeSystem;
public INameEnvironment nameEnvironment;
public CompilerOptions globalOptions;
@@ -151,6 +152,9 @@ public class LookupEnvironment implements ProblemReasons, TypeConstants {
PackageBinding nonnullAnnotationPackage; // the package supposed to contain the NonNull annotation type
PackageBinding nonnullByDefaultAnnotationPackage; // the package supposed to contain the NonNullByDefault annotation type
+ AnnotationBinding nonNullAnnotation;
+ AnnotationBinding nullableAnnotation;
+
final static int BUILD_FIELDS_AND_METHODS = 4;
final static int BUILD_TYPE_HIERARCHY = 1;
final static int CHECK_AND_SET_IMPORTS = 2;
@@ -186,7 +190,12 @@ public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOpt
this.accessRestrictions = new HashMap(3);
this.classFilePool = ClassFilePool.newInstance();
this.typesBeingConnected = new HashSet();
- this.typeSystem = new AnnotatableTypeSystem(this);
+ boolean stillTesting = true;
+ if (this.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8 && (stillTesting || this.globalOptions.storeAnnotations)) {
+ this.typeSystem = new AnnotatableTypeSystem(this);
+ } else {
+ this.typeSystem = new UnannotatedTypeSystem(this);
+ }
}
/**
@@ -431,7 +440,7 @@ public int internalCompleteTypeBindings(CompilationUnitDeclaration parsedUnit) {
//{ObjectTeams: one more step:
if (todo >= ROLES_LINKED)
RoleSplitter.linkRoles(this.unitBeingCompleted = parsedUnit);
-
+// SH}
this.unitBeingCompleted = null;
}
//{ObjectTeams: report actual step achieved:
@@ -848,22 +857,32 @@ public TypeBinding convertUnresolvedBinaryToRawType(TypeBinding type) {
}
return type;
}
-/*
- * Used to guarantee annotation identity: we do that only for marker annotations. We don't have the machinery for the general case as of now.
- */
+/* Used to guarantee annotation identity: we do that only for marker annotations and others with all default values.
+ We don't have the machinery for the general case as of now.
+*/
public AnnotationBinding createAnnotation(ReferenceBinding annotationType, ElementValuePair[] pairs) {
if (pairs.length != 0) {
AnnotationBinding.setMethodBindings(annotationType, pairs);
return new AnnotationBinding(annotationType, pairs);
}
- return this.typeSystem.getAnnotationType(annotationType);
+ return this.typeSystem.getAnnotationType(annotationType, true);
+}
+
+/* Used to guarantee annotation identity: we do that only for marker annotations and others with all default values.
+ We don't have the machinery for the general case as of now.
+*/
+public AnnotationBinding createUnresolvedAnnotation(ReferenceBinding annotationType, ElementValuePair[] pairs) {
+ if (pairs.length != 0) {
+ return new UnresolvedAnnotationBinding(annotationType, pairs, this);
+ }
+ return this.typeSystem.getAnnotationType(annotationType, false);
}
/*
* Used to guarantee array type identity.
*/
public ArrayBinding createArrayType(TypeBinding leafComponentType, int dimensionCount) {
- return this.typeSystem.getArrayType(leafComponentType, dimensionCount, Binding.NO_ANNOTATIONS);
+ return this.typeSystem.getArrayType(leafComponentType, dimensionCount);
}
public ArrayBinding createArrayType(TypeBinding leafComponentType, int dimensionCount, AnnotationBinding [] annotations) {
@@ -880,13 +899,13 @@ public TypeBinding createIntersectionCastType(ReferenceBinding[] intersectingTyp
if (count < length) {
if ((intersectionCastTypeBindings = this.uniqueIntersectionCastTypeBindings[count]) == null)
- this.uniqueIntersectionCastTypeBindings[count] = intersectionCastTypeBindings = new IntersectionCastTypeBinding[10];
+ this.uniqueIntersectionCastTypeBindings[count] = intersectionCastTypeBindings = new IntersectionCastTypeBinding[4];
} else {
System.arraycopy(
this.uniqueIntersectionCastTypeBindings, 0,
this.uniqueIntersectionCastTypeBindings = new IntersectionCastTypeBinding[count + 1][], 0,
length);
- this.uniqueIntersectionCastTypeBindings[count] = intersectionCastTypeBindings = new IntersectionCastTypeBinding[10];
+ this.uniqueIntersectionCastTypeBindings[count] = intersectionCastTypeBindings = new IntersectionCastTypeBinding[4];
}
int index = -1;
@@ -898,7 +917,7 @@ public TypeBinding createIntersectionCastType(ReferenceBinding[] intersectingTyp
ReferenceBinding [] priorIntersectingTypes = priorBinding.intersectingTypes;
for (int i = 0; i < count; i++) {
if (intersectingTypes[i] != priorIntersectingTypes[i])
- continue next;
+ continue next;
}
return priorBinding;
}
@@ -920,16 +939,12 @@ public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBin
// resolve any array bindings which reference the unresolvedType
ReferenceBinding cachedType = packageBinding.getType0(binaryBinding.compoundName[binaryBinding.compoundName.length - 1]);
- if (cachedType != null) { // update reference to unresolved binding after having read classfile (knows whether generic for raw conversion)
- if (cachedType instanceof UnresolvedReferenceBinding) {
- ((UnresolvedReferenceBinding) cachedType).setResolvedType(binaryBinding, this);
- } else {
- if (cachedType.isBinaryBinding()) // sanity check... at this point the cache should ONLY contain unresolved types
- return (BinaryTypeBinding) cachedType;
- // it is possible with a large number of source files (exceeding AbstractImageBuilder.MAX_AT_ONCE) that a member type can be in the cache as an UnresolvedType,
- // but because its enclosingType is resolved while its created (call to BinaryTypeBinding constructor), its replaced with a source type
- return null;
- }
+ if (cachedType != null && !cachedType.isUnresolvedType()) {
+ if (cachedType.isBinaryBinding()) // sanity check... at this point the cache should ONLY contain unresolved types
+ return (BinaryTypeBinding) cachedType;
+ // it is possible with a large number of source files (exceeding AbstractImageBuilder.MAX_AT_ONCE) that a member type can be in the cache as an UnresolvedType,
+ // but because its enclosingType is resolved while its created (call to BinaryTypeBinding constructor), its replaced with a source type
+ return null;
}
packageBinding.addType(binaryBinding);
setAccessRestriction(binaryBinding, accessRestriction);
@@ -1127,6 +1142,11 @@ public PolymorphicMethodBinding createPolymorphicMethod(MethodBinding originalPo
cachedInfo[index] = polymorphicMethod;
return polymorphicMethod;
}
+
+public boolean usesAnnotatedTypeSystem() {
+ return this.typeSystem.isAnnotatedTypeSystem();
+}
+
public MethodBinding updatePolymorphicMethodReturnType(PolymorphicMethodBinding binding, TypeBinding typeBinding) {
// update the return type to be the given return type, but reuse existing binding if one can match
String key = new String(binding.selector);
@@ -1179,9 +1199,15 @@ public ParameterizedMethodBinding createGetClassMethod(TypeBinding receiverType,
}
return retVal;
}
-
+public ReferenceBinding createMemberType(ReferenceBinding memberType, ReferenceBinding enclosingType) {
+ return this.typeSystem.getMemberType(memberType, enclosingType);
+}
public ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType) {
- return this.typeSystem.getParameterizedType(genericType, typeArguments, enclosingType, Binding.NO_ANNOTATIONS);
+ return this.typeSystem.getParameterizedType(genericType, typeArguments, null, -1, enclosingType);
+}
+
+public ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType, AnnotationBinding [] annotations) {
+ return this.typeSystem.getParameterizedType(genericType, typeArguments, null, -1, enclosingType, annotations);
}
//{ObjectTeams: for anchored role types:
@@ -1218,11 +1244,19 @@ public TypeBinding createAnnotatedType(TypeBinding type, AnnotationBinding[] new
}
public RawTypeBinding createRawType(ReferenceBinding genericType, ReferenceBinding enclosingType) {
- return this.typeSystem.getRawType(genericType, enclosingType, Binding.NO_ANNOTATIONS);
+ return this.typeSystem.getRawType(genericType, enclosingType);
+}
+
+public RawTypeBinding createRawType(ReferenceBinding genericType, ReferenceBinding enclosingType, AnnotationBinding [] annotations) {
+ return this.typeSystem.getRawType(genericType, enclosingType, annotations);
}
public WildcardBinding createWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind) {
- return this.typeSystem.getWildcard(genericType, rank, bound, otherBounds, boundKind, Binding.NO_ANNOTATIONS);
+ return this.typeSystem.getWildcard(genericType, rank, bound, otherBounds, boundKind);
+}
+
+public WildcardBinding createWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind, AnnotationBinding [] annotations) {
+ return this.typeSystem.getWildcard(genericType, rank, bound, otherBounds, boundKind, annotations);
}
/**
@@ -1255,8 +1289,10 @@ public ReferenceBinding getCachedType(char[][] compoundName) {
}
public AnnotationBinding getNullableAnnotation() {
+ if (this.nullableAnnotation != null)
+ return this.nullableAnnotation;
ReferenceBinding nullable = getResolvedType(this.globalOptions.nullableAnnotationName, null);
- return new AnnotationBinding(nullable, Binding.NO_ELEMENT_VALUE_PAIRS);
+ return this.nullableAnnotation = this.typeSystem.getAnnotationType(nullable, true);
}
public char[][] getNullableAnnotationName() {
@@ -1264,8 +1300,18 @@ public char[][] getNullableAnnotationName() {
}
public AnnotationBinding getNonNullAnnotation() {
+ if (this.nonNullAnnotation != null)
+ return this.nonNullAnnotation;
ReferenceBinding nonNull = getResolvedType(this.globalOptions.nonNullAnnotationName, null);
- return new AnnotationBinding(nonNull, Binding.NO_ELEMENT_VALUE_PAIRS);
+ return this.nonNullAnnotation = this.typeSystem.getAnnotationType(nonNull, true);
+}
+
+public AnnotationBinding[] nullAnnotationsFromTagBits(long nullTagBits) {
+ if (nullTagBits == TagBits.AnnotationNonNull)
+ return new AnnotationBinding[] { getNonNullAnnotation() };
+ else if (nullTagBits == TagBits.AnnotationNullable)
+ return new AnnotationBinding[] { getNullableAnnotation() };
+ return null;
}
public char[][] getNonNullAnnotationName() {
@@ -1521,7 +1567,7 @@ TypeBinding getTypeFromSignature(char[] signature, int start, int end, boolean i
start++;
dimension++;
}
- // null annotations on dimensions?
+ // annotations on dimensions?
AnnotationBinding [][] annotationsOnDimensions = null;
if (dimension > 0 && walker != TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
for (int i = 0; i < dimension; i++) {
@@ -1577,16 +1623,27 @@ TypeBinding getTypeFromSignature(char[] signature, int start, int end, boolean i
binding = getTypeFromConstantPoolName(signature, start + 1, end, isParameterized, missingTypeNames); // skip leading 'L' or 'T'
}
- int depth = binding.depth();
- while (depth > 0 && walker != TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) { // we are dropping annotations on enclosing types.
- walker = walker.toNextNestedType();
- depth--;
+ if (isParameterized) {
+ if (dimension != 0)
+ throw new IllegalStateException();
+ return binding;
}
- AnnotationBinding [][] annotations = new AnnotationBinding[depth + 1][];
- annotations[depth] = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
- if (annotations[depth] != null && annotations[depth] != Binding.NO_ANNOTATIONS)
- binding = createAnnotatedType(binding, annotations);
+ if (walker != TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
+ final int depth = binding.depth();
+ AnnotationBinding [][] annotations = null;
+ for (int i = 0; i <= depth; i++) {
+ AnnotationBinding[] annots = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
+ if (annots != null && annots.length > 0) {
+ if (annotations == null)
+ annotations = new AnnotationBinding[depth + 1][];
+ annotations[i] = annots;
+ }
+ walker = walker.toNextNestedType();
+ }
+ if (annotations != null)
+ binding = createAnnotatedType(binding, annotations);
+ }
if (dimension != 0)
binding = this.typeSystem.getArrayType(binding, dimension, AnnotatableTypeSystem.flattenedAnnotations(annotationsOnDimensions));
@@ -1622,12 +1679,25 @@ public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariab
wrapper.start++;
dimension++;
}
+ // annotations on dimensions?
+ AnnotationBinding [][] annotationsOnDimensions = null;
+ if (dimension > 0 && walker != TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
+ for (int i = 0; i < dimension; i++) {
+ AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
+ if (annotations != Binding.NO_ANNOTATIONS) {
+ if (annotationsOnDimensions == null)
+ annotationsOnDimensions = new AnnotationBinding[dimension][];
+ annotationsOnDimensions[i] = annotations;
+ }
+ walker = walker.toNextArrayDimension();
+ }
+ }
if (wrapper.signature[wrapper.start] == 'T') {
int varStart = wrapper.start + 1;
int varEnd = wrapper.computeEnd();
for (int i = staticVariables.length; --i >= 0;)
if (CharOperation.equals(staticVariables[i].sourceName, wrapper.signature, varStart, varEnd))
- return typeFromTypeVariable(staticVariables[i], dimension, walker, missingTypeNames);
+ return getTypeFromTypeVariable(staticVariables[i], dimension, annotationsOnDimensions, walker, missingTypeNames);
ReferenceBinding initialType = enclosingType;
do {
TypeVariableBinding[] enclosingTypeVariables;
@@ -1638,7 +1708,7 @@ public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariab
}
for (int i = enclosingTypeVariables.length; --i >= 0;)
if (CharOperation.equals(enclosingTypeVariables[i].sourceName, wrapper.signature, varStart, varEnd))
- return typeFromTypeVariable(enclosingTypeVariables[i], dimension, walker, missingTypeNames);
+ return getTypeFromTypeVariable(enclosingTypeVariables[i], dimension, annotationsOnDimensions, walker, missingTypeNames);
} while ((enclosingType = enclosingType.enclosingType()) != null);
this.problemReporter.undefinedTypeVariableSignature(CharOperation.subarray(wrapper.signature, varStart, varEnd), initialType);
return null; // cannot reach this, since previous problem will abort compilation
@@ -1647,7 +1717,7 @@ public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariab
TypeBinding type = getTypeFromSignature(wrapper.signature, wrapper.start, wrapper.computeEnd(), isParameterized = (wrapper.end == wrapper.bracket), enclosingType, missingTypeNames, walker);
if (!isParameterized)
- return dimension == 0 ? type : createArrayType(type, dimension);
+ return dimension == 0 ? type : createArrayType(type, dimension, AnnotatableTypeSystem.flattenedAnnotations(annotationsOnDimensions));
// type must be a ReferenceBinding at this point, cannot be a BaseTypeBinding or ArrayTypeBinding
ReferenceBinding actualType = (ReferenceBinding) type;
@@ -1658,8 +1728,9 @@ public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariab
if (actualEnclosing != null) { // convert needed if read some static member type
actualEnclosing = (ReferenceBinding) convertToRawType(actualEnclosing, false /*do not force conversion of enclosing types*/);
}
+ AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
TypeBinding[] typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, actualType, missingTypeNames, walker);
- ParameterizedTypeBinding parameterizedType = createParameterizedType(actualType, typeArguments, actualEnclosing);
+ ParameterizedTypeBinding parameterizedType = createParameterizedType(actualType, typeArguments, actualEnclosing, annotations);
while (wrapper.signature[wrapper.start] == '.') {
wrapper.start++; // skip '.'
@@ -1670,37 +1741,25 @@ public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariab
// need to protect against the member type being null when the signature is invalid
if (memberType == null)
this.problemReporter.corruptedSignature(parameterizedType, wrapper.signature, memberStart); // aborts
+ walker = walker.toNextNestedType();
+ annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
if (wrapper.signature[wrapper.start] == '<') {
wrapper.start++; // skip '<'
typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, memberType, missingTypeNames, walker);
} else {
typeArguments = null;
}
- parameterizedType = createParameterizedType(memberType, typeArguments, parameterizedType);
+ parameterizedType = createParameterizedType(memberType, typeArguments, parameterizedType, annotations);
}
wrapper.start++; // skip ';'
- return dimension == 0 ? (TypeBinding) parameterizedType : createArrayType(parameterizedType, dimension);
+ return dimension == 0 ? (TypeBinding) parameterizedType : createArrayType(parameterizedType, dimension, AnnotatableTypeSystem.flattenedAnnotations(annotationsOnDimensions));
}
-private TypeBinding typeFromTypeVariable(TypeVariableBinding typeVariableBinding, int dimension, TypeAnnotationWalker walker, char [][][] missingTypeNames) {
- AnnotationBinding [] annotations;
- AnnotationBinding [][] annotationsOnDimensions = null;
- if (walker != TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
- for (int i = 0; i < dimension; i++) {
- annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
- if (annotations != Binding.NO_ANNOTATIONS) {
- if (annotationsOnDimensions == null)
- annotationsOnDimensions = new AnnotationBinding[dimension][];
- annotationsOnDimensions[i] = annotations;
- }
- walker = walker.toNextArrayDimension();
- }
- }
-
- annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
+private TypeBinding getTypeFromTypeVariable(TypeVariableBinding typeVariableBinding, int dimension, AnnotationBinding [][] annotationsOnDimensions, TypeAnnotationWalker walker, char [][][] missingTypeNames) {
+ AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(), this, missingTypeNames);
if (annotations != null && annotations != Binding.NO_ANNOTATIONS)
typeVariableBinding = (TypeVariableBinding) createAnnotatedType(typeVariableBinding, new AnnotationBinding [][] { annotations });
-
+
if (dimension == 0) {
return typeVariableBinding;
}
@@ -1857,4 +1916,9 @@ public void addResolutionListener(IQualifiedTypeResolutionListener resolutionLis
public TypeBinding getUnannotatedType(TypeBinding typeBinding) {
return this.typeSystem.getUnannotatedType(typeBinding);
}
+
+// Given a type, return all its variously annotated versions.
+public TypeBinding[] getAnnotatedTypes(TypeBinding type) {
+ return this.typeSystem.getAnnotatedTypes(type);
+}
} \ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java
index c2dbeef61..a4cefa411 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MemberTypeBinding.java
@@ -54,6 +54,7 @@ public MemberTypeBinding(MemberTypeBinding prototype) {
}
void checkSyntheticArgsAndFields() {
+ if (this != this.prototype) throw new IllegalStateException();
//{ObjectTeams: role ifcs require synth args too
/* orig:
if (isStatic()) return;
@@ -89,10 +90,9 @@ public char[] constantPoolName() /* java/lang/Object */ {
return this.constantPoolName = CharOperation.concat(enclosingType().constantPoolName(), this.sourceName, '$');
}
-public TypeBinding clone(TypeBinding outerType, TypeBinding[] typeArguments) {
+public TypeBinding clone(TypeBinding outerType) {
MemberTypeBinding copy = new MemberTypeBinding(this);
- if (outerType != null)
- copy.enclosingType = (SourceTypeBinding) outerType;
+ copy.enclosingType = (SourceTypeBinding) outerType;
return copy;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
index 9f3690258..403aaedf3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
@@ -21,6 +21,7 @@
* bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
* bug 388281 - [compiler][null] inheritance of null annotations as an option
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Jesper Steen Moller - Contributions for
* Bug 412150 [1.8] [compiler] Enable reflected parameter names during annotation processing
*******************************************************************************/
@@ -499,9 +500,9 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
// Static interface methods can be explicitly invoked only through the type reference of the declaring interface or implicitly in the interface itself.
if (scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_8)
return false;
- if (invocationSite.isTypeAccess() && receiverType == this.declaringClass)
+ if (invocationSite.isTypeAccess() && TypeBinding.equalsEquals(receiverType, this.declaringClass))
return true;
- if (invocationSite.receiverIsImplicitThis() && invocationType == this.declaringClass)
+ if (invocationSite.receiverIsImplicitThis() && TypeBinding.equalsEquals(invocationType, this.declaringClass))
return true;
return false;
}
@@ -536,9 +537,9 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
// SH}
//{ObjectTeams: use receiverClass:
/* orig:
- if (invocationType == this.declaringClass && invocationType == receiverType) return true;
+ if (TypeBinding.equalsEquals(invocationType, this.declaringClass) && TypeBinding.equalsEquals(invocationType, receiverType)) return true;
:giro */
- if (invocationType == this.declaringClass && invocationType == receiverClass) return true;
+ if (TypeBinding.equalsEquals(invocationType, this.declaringClass) && TypeBinding.equalsEquals(invocationType, receiverClass)) return true;
// SH}
if (invocationType == null) // static import call
@@ -555,7 +556,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
// AND the receiverType is the invocationType or its subclass
// OR the method is a static method accessed directly through a type
// OR previous assertions are true for one of the enclosing type
- if (invocationType == this.declaringClass) return true;
+ if (TypeBinding.equalsEquals(invocationType, this.declaringClass)) return true;
if (invocationType.fPackage == this.declaringClass.fPackage) return true;
ReferenceBinding currentType = invocationType;
@@ -578,7 +579,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
if (depth > 0) invocationSite.setDepth(depth);
return true; // see 1FMEPDL - return invocationSite.isTypeAccess();
}
- if (currentType == receiverErasure || receiverErasure.findSuperTypeOriginatingFrom(currentType) != null) {
+ if (TypeBinding.equalsEquals(currentType, receiverErasure) || receiverErasure.findSuperTypeOriginatingFrom(currentType) != null) {
if (depth > 0) invocationSite.setDepth(depth);
return true;
}
@@ -600,7 +601,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
// answer true if the receiverType is the declaringClass
// AND the invocationType and the declaringClass have a common enclosingType
receiverCheck: {
- if (receiverType != this.declaringClass) {
+ if (TypeBinding.notEquals(receiverType, this.declaringClass)) {
// special tolerance for type variable direct bounds, but only if compliance <= 1.6, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=334622
if (scope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_6 && receiverType.isTypeVariable() && ((TypeVariableBinding) receiverType).isErasureBoundTo(this.declaringClass.erasure()))
break receiverCheck;
@@ -608,7 +609,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
}
}
- if (invocationType != this.declaringClass) {
+ if (TypeBinding.notEquals(invocationType, this.declaringClass)) {
ReferenceBinding outerInvocationType = invocationType;
ReferenceBinding temp = outerInvocationType.enclosingType();
while (temp != null) {
@@ -622,7 +623,7 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
outerDeclaringClass = temp;
temp = temp.enclosingType();
}
- if (outerInvocationType != outerDeclaringClass) return false;
+ if (TypeBinding.notEquals(outerInvocationType, outerDeclaringClass)) return false;
}
return true;
//{ObjectTeams: reset:
@@ -648,9 +649,9 @@ public final boolean canBeSeenBy(TypeBinding receiverType, InvocationSite invoca
// SH}
do {
if (currentType.isCapture()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=285002
- if (originalDeclaringClass == currentType.erasure().original()) return true;
+ if (TypeBinding.equalsEquals(originalDeclaringClass, currentType.erasure().original())) return true;
} else {
- if (originalDeclaringClass == currentType.original()) return true;
+ if (TypeBinding.equalsEquals(originalDeclaringClass, currentType.original())) return true;
}
PackageBinding currentPackage = currentType.fPackage;
// package could be null for wildcards/intersection types, ignore and recurse in superclass
@@ -907,7 +908,7 @@ protected void fillInDefaultNonNullness(AbstractMethodDeclaration sourceMethod)
this.tagBits |= TagBits.HasParameterAnnotations;
if ( this.returnType != null
&& !this.returnType.isBaseType()
- && (this.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) == 0)
+ && (this.tagBits & TagBits.AnnotationNullMASK) == 0)
{
this.tagBits |= TagBits.AnnotationNonNull;
} else if (sourceMethod != null && (this.tagBits & TagBits.AnnotationNonNull) != 0) {
@@ -926,8 +927,7 @@ protected void fillInDefaultNonNullness18(AbstractMethodDeclaration sourceMethod
if (existing == 0L) {
added = true;
if (!parameter.isBaseType()) {
- // TODO(Stephan): Synthesize AnnotationBinding[] and call LE#createAnnotatedType(TB, AB[]);
- // this.parameters[i] = env.createAnnotatedType(parameter, TagBits.AnnotationNonNull);
+ this.parameters[i] = env.createAnnotatedType(parameter, new AnnotationBinding[]{env.getNonNullAnnotation()});
if (sourceMethod != null)
sourceMethod.arguments[i].binding.type = this.parameters[i];
}
@@ -939,10 +939,9 @@ protected void fillInDefaultNonNullness18(AbstractMethodDeclaration sourceMethod
this.tagBits |= TagBits.HasParameterAnnotations;
if ( this.returnType != null
&& !this.returnType.isBaseType()
- && (this.returnType.tagBits & (TagBits.AnnotationNonNull|TagBits.AnnotationNullable)) == 0)
+ && (this.returnType.tagBits & TagBits.AnnotationNullMASK) == 0)
{
- // TODO(Stephan: Synthesize AnnotationBinding[] and call LE#createAnnotatedType(TB, AB[]);
- // this.returnType = env.createAnnotatedType(this.returnType, TagBits.AnnotationNonNull);
+ this.returnType = env.createAnnotatedType(this.returnType, new AnnotationBinding[]{env.getNonNullAnnotation()});
} else if (sourceMethod != null && (this.returnType.tagBits & TagBits.AnnotationNonNull) != 0) {
sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, -1/*signifies method return*/);
}
@@ -1711,7 +1710,7 @@ public final char[] signature(ClassFile classFile) {
}
//{ObjectTeams: 'weaken' to that erasure that was used in the tsuper version:
/* orig:
- buffer.append(this.returnType.signature());
+ buffer.append(this.returnType.signature());
:giro */
buffer.append(getCodeGenType(-1).signature());
// SH}
@@ -1782,6 +1781,7 @@ public String toString(boolean showModifiers) {
}
//{ObjectTeams: print only conditionally:
if (showModifiers)
+// SH}
ASTNode.printModifiers(this.modifiers, output);
output.append(this.returnType != null ? this.returnType.debugName() : "<no type>"); //$NON-NLS-1$
output.append(" "); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MissingTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MissingTypeBinding.java
index 46b28059b..3281d4393 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MissingTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MissingTypeBinding.java
@@ -43,10 +43,6 @@ public MissingTypeBinding(PackageBinding packageBinding, char[][] compoundName,
this.methods = Binding.NO_METHODS;
}
-public MissingTypeBinding(MissingTypeBinding prototype) {
- super(prototype);
-}
-
//{ObjectTeams: missing o.o.Team cannot be further initialized:
@Override
protected void setupOrgObjectteamsTeamModel() {
@@ -55,14 +51,6 @@ protected void setupOrgObjectteamsTeamModel() {
}
// SH}
-public TypeBinding clone(TypeBinding outerType, TypeBinding[] typeArguments) {
- MissingTypeBinding copy = new MissingTypeBinding(this);
- copy.enclosingType = (ReferenceBinding) outerType; // for better or worse.
- return copy;
-}
-public TypeBinding unannotated() {
- return this.prototype;
-}
/**
* @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#collectMissingTypes(java.util.List)
*/
@@ -90,13 +78,10 @@ public int problemId() {
* @see LookupEnvironment#createMissingType(PackageBinding, char[][])
*/
void setMissingSuperclass(ReferenceBinding missingSuperclass) {
- if (this != this.prototype) {
- ((MissingTypeBinding) this.prototype).setMissingSuperclass(missingSuperclass);
- }
this.superclass = missingSuperclass;
}
public String toString() {
- return this.hasTypeAnnotations() ? annotatedDebugName() + " (missing)" : "[MISSING:" + new String(CharOperation.concatWith(this.compoundName, '.')) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-}
+ return "[MISSING:" + new String(CharOperation.concatWith(this.compoundName, '.')) + "]"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
index aa1f04403..97d4c3ccc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/NestedTypeBinding.java
@@ -4,6 +4,10 @@
* 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
@@ -46,6 +50,9 @@ public NestedTypeBinding(NestedTypeBinding prototype) {
* Answer the new argument or the existing argument if one already existed.
*/
public SyntheticArgumentBinding addSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) {
+
+ if (this != this.prototype) throw new IllegalStateException();
+
SyntheticArgumentBinding synthLocal = null;
if (this.outerLocalVariables == null) {
@@ -76,6 +83,7 @@ public SyntheticArgumentBinding addSyntheticArgument(LocalVariableBinding actual
* Answer the new argument or the existing argument if one already existed.
*/
public SyntheticArgumentBinding addSyntheticArgument(ReferenceBinding targetEnclosingType) {
+ if (this != this.prototype) throw new IllegalStateException();
SyntheticArgumentBinding synthLocal = null;
if (this.enclosingInstances == null) {
synthLocal = new SyntheticArgumentBinding(targetEnclosingType);
@@ -100,6 +108,7 @@ public SyntheticArgumentBinding addSyntheticArgument(ReferenceBinding targetEncl
* Answer the new argument or the existing argument if one already existed.
*/
public SyntheticArgumentBinding addSyntheticArgumentAndField(LocalVariableBinding actualOuterLocalVariable) {
+ if (this != this.prototype) throw new IllegalStateException();
SyntheticArgumentBinding synthLocal = addSyntheticArgument(actualOuterLocalVariable);
if (synthLocal == null) return null;
@@ -112,6 +121,7 @@ public SyntheticArgumentBinding addSyntheticArgumentAndField(LocalVariableBindin
* Answer the new argument or the existing argument if one already existed.
*/
public SyntheticArgumentBinding addSyntheticArgumentAndField(ReferenceBinding targetEnclosingType) {
+ if (this != this.prototype) throw new IllegalStateException();
SyntheticArgumentBinding synthLocal = addSyntheticArgument(targetEnclosingType);
if (synthLocal == null) return null;
@@ -121,6 +131,7 @@ public SyntheticArgumentBinding addSyntheticArgumentAndField(ReferenceBinding ta
}
protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation[] annotations, long annotationTagBits) {
+ if (this != this.prototype) throw new IllegalStateException();
ReferenceBinding currentType = this.enclosingType;
do {
if (!((SourceTypeBinding)currentType).checkRedundantNullnessDefaultOne(location, annotations, annotationTagBits)) {
@@ -141,6 +152,7 @@ public ReferenceBinding enclosingType() {
* @return the enclosingInstancesSlotSize
*/
public int getEnclosingInstancesSlotSize() {
+ if (this != this.prototype) throw new IllegalStateException();
return this.enclosingInstances == null ? 0 : this.enclosingInstances.length;
}
@@ -148,6 +160,7 @@ public int getEnclosingInstancesSlotSize() {
* @return the outerLocalVariablesSlotSize
*/
public int getOuterLocalVariablesSlotSize() {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.outerLocalVariablesSlotSize < 0) {
this.outerLocalVariablesSlotSize = 0;
int outerLocalsCount = this.outerLocalVariables == null ? 0 : this.outerLocalVariables.length;
@@ -170,6 +183,7 @@ public int getOuterLocalVariablesSlotSize() {
/* Answer the synthetic argument for <actualOuterLocalVariable> or null if one does not exist.
*/
public SyntheticArgumentBinding getSyntheticArgument(LocalVariableBinding actualOuterLocalVariable) {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.outerLocalVariables == null) return null; // is null if no outer local variables are known
for (int i = this.outerLocalVariables.length; --i >= 0;)
if (this.outerLocalVariables[i].actualOuterLocalVariable == actualOuterLocalVariable)
@@ -180,6 +194,9 @@ public SyntheticArgumentBinding getSyntheticArgument(LocalVariableBinding actual
/* Answer the synthetic argument for <targetEnclosingType> or null if one does not exist.
*/
public SyntheticArgumentBinding getSyntheticArgument(ReferenceBinding targetEnclosingType, boolean onlyExactMatch, boolean scopeIsConstructorCall) {
+
+ if (this != this.prototype) throw new IllegalStateException();
+
if (this.enclosingInstances == null) return null; // is null if no enclosing instances are known
// exact match
@@ -218,10 +235,12 @@ public SyntheticArgumentBinding getSyntheticArgument(ReferenceBinding targetEncl
}
public SyntheticArgumentBinding[] syntheticEnclosingInstances() {
+ if (this != this.prototype) throw new IllegalStateException();
return this.enclosingInstances; // is null if no enclosing instances are required
}
public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.enclosingTypes == UNINITIALIZED_REFERENCE_TYPES) {
//{ObjectTeams: enclosing instances of local types are set during analyzeCode:
if (this.isLocalType())
@@ -241,6 +260,7 @@ public ReferenceBinding[] syntheticEnclosingInstanceTypes() {
}
public SyntheticArgumentBinding[] syntheticOuterLocalVariables() {
+ if (this != this.prototype) throw new IllegalStateException();
return this.outerLocalVariables; // is null if no outer locals are required
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
index 0c6cd255e..cab1ec097 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PackageBinding.java
@@ -1,10 +1,13 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 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
- * $Id: PackageBinding.java 23405 2010-02-03 17:02:18Z stephan $
+ *
+ * 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
@@ -79,7 +82,11 @@ void addType(ReferenceBinding element) {
if ((element.tagBits & TagBits.HasMissingType) == 0) clearMissingTagBit();
if (this.knownTypes == null)
this.knownTypes = new HashtableOfType(25);
- this.knownTypes.put(element.compoundName[element.compoundName.length - 1], element);
+ char [] name = element.compoundName[element.compoundName.length - 1];
+ ReferenceBinding priorType = this.knownTypes.getput(name, element);
+ if (priorType != null && priorType.isUnresolvedType() && !element.isUnresolvedType()) {
+ ((UnresolvedReferenceBinding) priorType).setResolvedType(element, this.environment);
+ }
if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled)
if (element.isAnnotationType() || element instanceof UnresolvedReferenceBinding) // unresolved types don't yet have the modifiers set
checkIfNullAnnotationType(element);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
index cbce3ddc7..621fa2b48 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedGenericMethodBinding.java
@@ -569,7 +569,7 @@ public class ParameterizedGenericMethodBinding extends ParameterizedMethodBindin
return Scope.substitute(new LingeringTypeVariableEliminator(this.variables, null, this.scope), this.substitutes[typeVariable.rank]);
}
ReferenceBinding genericType = (ReferenceBinding) (typeVariable.declaringElement instanceof ReferenceBinding ? typeVariable.declaringElement : null);
- return this.scope.environment().createWildcard(genericType, typeVariable.rank, null, null, Wildcard.UNBOUND);
+ return this.scope.environment().createWildcard(genericType, typeVariable.rank, null, null, Wildcard.UNBOUND, typeVariable.getTypeAnnotations());
}
public LookupEnvironment environment() {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
index 3c235005a..653f0cf68 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
@@ -17,9 +17,11 @@
* bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
* bug 392384 - [1.8][compiler][null] Restore nullness info from type annotations in class files
* Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
+import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.ITeamAnchor;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
@@ -106,25 +108,27 @@ public class ParameterizedMethodBinding extends MethodBinding {
TypeBinding substitutedSuperclass = Scope.substitute(substitution, originalVariable.superclass);
ReferenceBinding[] substitutedInterfaces = Scope.substitute(substitution, originalVariable.superInterfaces);
if (originalVariable.firstBound != null) {
- substitutedVariable.firstBound = originalVariable.firstBound == originalVariable.superclass
+ TypeBinding firstBound;
+ firstBound = originalVariable.firstBound == originalVariable.superclass
? substitutedSuperclass // could be array type or interface
: substitutedInterfaces[0];
+ substitutedVariable.setFirstBound(firstBound);
}
switch (substitutedSuperclass.kind()) {
case Binding.ARRAY_TYPE :
- substitutedVariable.superclass = parameterizedDeclaringClass.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
- substitutedVariable.superInterfaces = substitutedInterfaces;
+ substitutedVariable.setSuperClass(parameterizedDeclaringClass.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null));
+ substitutedVariable.setSuperInterfaces(substitutedInterfaces);
break;
default:
if (substitutedSuperclass.isInterface()) {
- substitutedVariable.superclass = parameterizedDeclaringClass.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
+ substitutedVariable.setSuperClass(parameterizedDeclaringClass.environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null));
int interfaceCount = substitutedInterfaces.length;
System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount);
substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass;
- substitutedVariable.superInterfaces = substitutedInterfaces;
+ substitutedVariable.setSuperInterfaces(substitutedInterfaces);
} else {
- substitutedVariable.superclass = (ReferenceBinding) substitutedSuperclass; // typeVar was extending other typeVar which got substituted with interface
- substitutedVariable.superInterfaces = substitutedInterfaces;
+ substitutedVariable.setSuperClass((ReferenceBinding) substitutedSuperclass); // typeVar was extending other typeVar which got substituted with interface
+ substitutedVariable.setSuperInterfaces(substitutedInterfaces);
}
}
}
@@ -138,14 +142,14 @@ public class ParameterizedMethodBinding extends MethodBinding {
// after substitution transfer nullness information from type annotations:
if (parameterizedDeclaringClass.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
- long returnNullBits = this.returnType.tagBits & TagBits.AnnotationNullMASK;
+ long returnNullBits = NullAnnotationMatching.validNullTagBits(this.returnType.tagBits);
if (returnNullBits != 0L) {
this.tagBits &= ~TagBits.AnnotationNullMASK;
this.tagBits |= returnNullBits;
}
int parametersLen = this.parameters.length;
for (int i=0; i<parametersLen; i++) {
- long paramTagBits = this.parameters[i].tagBits & TagBits.AnnotationNullMASK;
+ long paramTagBits = NullAnnotationMatching.validNullTagBits(this.parameters[i].tagBits);
if (paramTagBits != 0) {
if (this.parameterNonNullness == null)
this.parameterNonNullness = new Boolean[parametersLen];
@@ -246,25 +250,27 @@ public class ParameterizedMethodBinding extends MethodBinding {
TypeBinding substitutedSuperclass = Scope.substitute(substitution, originalVariable.superclass);
ReferenceBinding[] substitutedInterfaces = Scope.substitute(substitution, originalVariable.superInterfaces);
if (originalVariable.firstBound != null) {
- substitutedVariable.firstBound = originalVariable.firstBound == originalVariable.superclass
+ TypeBinding firstBound;
+ firstBound = originalVariable.firstBound == originalVariable.superclass
? substitutedSuperclass // could be array type or interface
: substitutedInterfaces[0];
+ substitutedVariable.setFirstBound(firstBound);
}
switch (substitutedSuperclass.kind()) {
case Binding.ARRAY_TYPE :
- substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
- substitutedVariable.superInterfaces = substitutedInterfaces;
+ substitutedVariable.setSuperClass(environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null));
+ substitutedVariable.setSuperInterfaces(substitutedInterfaces);
break;
default:
if (substitutedSuperclass.isInterface()) {
- substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
+ substitutedVariable.setSuperClass(environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null));
int interfaceCount = substitutedInterfaces.length;
System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount);
substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass;
- substitutedVariable.superInterfaces = substitutedInterfaces;
+ substitutedVariable.setSuperInterfaces(substitutedInterfaces);
} else {
- substitutedVariable.superclass = (ReferenceBinding) substitutedSuperclass; // typeVar was extending other typeVar which got substituted with interface
- substitutedVariable.superInterfaces = substitutedInterfaces;
+ substitutedVariable.setSuperClass((ReferenceBinding) substitutedSuperclass); // typeVar was extending other typeVar which got substituted with interface
+ substitutedVariable.setSuperInterfaces(substitutedInterfaces);
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
index c2887368f..52f873362 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
@@ -71,14 +71,6 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
public ParameterizedTypeBinding(ReferenceBinding type, TypeBinding[] arguments, ReferenceBinding enclosingType, LookupEnvironment environment){
this.environment = environment;
this.enclosingType = enclosingType; // never unresolved, never lazy per construction
-// if (enclosingType != null && enclosingType.isGenericType()) {
-// RuntimeException e = new RuntimeException("PARAM TYPE with GENERIC ENCLOSING");
-// e.printStackTrace();
-// throw e;
-// }
-// if (!(type instanceof UnresolvedReferenceBinding) && type.typeVariables() == Binding.NO_TYPE_VARIABLES) {
-// System.out.println();
-// }
initialize(type, arguments);
if (type instanceof UnresolvedReferenceBinding)
((UnresolvedReferenceBinding) type).addWrapper(this, environment);
@@ -178,7 +170,7 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
capturedArguments[i] = argument;
}
}
- ParameterizedTypeBinding capturedParameterizedType = this.environment.createParameterizedType(this.type, capturedArguments, enclosingType());
+ ParameterizedTypeBinding capturedParameterizedType = this.environment.createParameterizedType(this.type, capturedArguments, enclosingType(), this.typeAnnotations);
for (int i = 0; i < length; i++) {
TypeBinding argument = capturedArguments[i];
if (argument.isCapture()) {
@@ -372,11 +364,8 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
return this.type.constantPoolName(); // erasure
}
- public TypeBinding clone(TypeBinding outerType, TypeBinding[] typeArguments) {
- ParameterizedTypeBinding copy = new ParameterizedTypeBinding(this.type, typeArguments, (ReferenceBinding) outerType, this.environment);
- if (this.hasTypeAnnotations())
- copy.setTypeAnnotations(this.getTypeAnnotations(), this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled);
- return copy;
+ public TypeBinding clone(TypeBinding outerType) {
+ return new ParameterizedTypeBinding(this.type, this.arguments, (ReferenceBinding) outerType, this.environment);
}
public ParameterizedMethodBinding createParameterizedMethod(MethodBinding originalMethod) {
@@ -851,7 +840,7 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
case Binding.PARAMETERIZED_TYPE :
ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
- if (this.type != otherParamType.type)
+ if (TypeBinding.notEquals(this.type, otherParamType.type))
return false;
if (!isStatic()) { // static member types do not compare their enclosing
ReferenceBinding enclosing = enclosingType();
@@ -859,7 +848,7 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
ReferenceBinding otherEnclosing = otherParamType.enclosingType();
if (otherEnclosing == null) return false;
if ((otherEnclosing.tagBits & TagBits.HasDirectWildcard) == 0) {
- if (enclosing != otherEnclosing) return false;
+ if (TypeBinding.notEquals(enclosing, otherEnclosing)) return false;
} else {
if (!enclosing.isEquivalentTo(otherParamType.enclosingType())) return false;
}
@@ -874,9 +863,6 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
for (int i = 0; i < length; i++) {
if (!this.arguments[i].isTypeArgumentContainedBy(otherArguments[i]))
return false;
- // Stephan : is this intentional ??
-// if ((this.arguments[i].tagBits & TagBits.AnnotationNullMASK) != (otherArguments[i].tagBits & TagBits.AnnotationNullMASK))
-// return false;
}
return true;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java
index caf7fff29..4013dc59d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/RawTypeBinding.java
@@ -77,11 +77,8 @@ public class RawTypeBinding extends ParameterizedTypeBinding {
return uniqueKey;
}
- public TypeBinding clone(TypeBinding outerType, TypeBinding[] typeArguments) {
- RawTypeBinding copy = new RawTypeBinding(this.actualType(), (ReferenceBinding) outerType, this.environment);
- if (this.hasTypeAnnotations())
- copy.setTypeAnnotations(this.getTypeAnnotations(), this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled);
- return copy;
+ public TypeBinding clone(TypeBinding outerType) {
+ return new RawTypeBinding(this.actualType(), (ReferenceBinding) outerType, this.environment);
}
/**
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index 6b4ee908a..e1c7e1da3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -31,6 +31,7 @@
* Bug 416176 - [1.8][compiler][null] null type annotations cause grief on type variables
* Jesper S Moller - Contributions for
* bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
+ * bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -408,7 +409,7 @@ public final boolean canBeSeenBy(PackageBinding invocationPackage) {
public final boolean canBeSeenBy(ReferenceBinding receiverType, ReferenceBinding invocationType) {
if (isPublic()) return true;
- if (invocationType == this && invocationType == receiverType) return true;
+ if (TypeBinding.equalsEquals(invocationType, this) && TypeBinding.equalsEquals(invocationType, receiverType)) return true;
if (isProtected()) {
// answer true if the invocationType is the declaringClass or they are in the same package
@@ -416,12 +417,12 @@ public final boolean canBeSeenBy(ReferenceBinding receiverType, ReferenceBinding
// AND the invocationType is the invocationType or its subclass
// OR the type is a static method accessed directly through a type
// OR previous assertions are true for one of the enclosing type
- if (invocationType == this) return true;
+ if (TypeBinding.equalsEquals(invocationType, this)) return true;
if (invocationType.fPackage == this.fPackage) return true;
TypeBinding currentType = invocationType.erasure();
TypeBinding declaringClass = enclosingType().erasure(); // protected types always have an enclosing one
- if (declaringClass == invocationType) return true;
+ if (TypeBinding.equalsEquals(declaringClass, invocationType)) return true;
if (declaringClass == null) return false; // could be null if incorrect top-level protected type
//int depth = 0;
do {
@@ -436,7 +437,7 @@ public final boolean canBeSeenBy(ReferenceBinding receiverType, ReferenceBinding
// answer true if the receiverType is the receiver or its enclosingType
// AND the invocationType and the receiver have a common enclosingType
receiverCheck: {
- if (!(receiverType == this || receiverType == enclosingType())) {
+ if (!(TypeBinding.equalsEquals(receiverType, this) || TypeBinding.equalsEquals(receiverType, enclosingType()))) {
// special tolerance for type variable direct bounds, but only if compliance <= 1.6, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=334622
if (receiverType.isTypeVariable()) {
TypeVariableBinding typeVariable = (TypeVariableBinding) receiverType;
@@ -447,7 +448,7 @@ public final boolean canBeSeenBy(ReferenceBinding receiverType, ReferenceBinding
}
}
- if (invocationType != this) {
+ if (TypeBinding.notEquals(invocationType, this)) {
ReferenceBinding outerInvocationType = invocationType;
ReferenceBinding temp = outerInvocationType.enclosingType();
while (temp != null) {
@@ -461,7 +462,7 @@ public final boolean canBeSeenBy(ReferenceBinding receiverType, ReferenceBinding
outerDeclaringClass = temp;
temp = temp.enclosingType();
}
- if (outerInvocationType != outerDeclaringClass) return false;
+ if (TypeBinding.notEquals(outerInvocationType, outerDeclaringClass)) return false;
}
return true;
}
@@ -473,9 +474,9 @@ public final boolean canBeSeenBy(ReferenceBinding receiverType, ReferenceBinding
TypeBinding originalDeclaringClass = (enclosingType() == null ? this : enclosingType()).original();
do {
if (currentType.isCapture()) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=285002
- if (originalDeclaringClass == currentType.erasure().original()) return true;
+ if (TypeBinding.equalsEquals(originalDeclaringClass, currentType.erasure().original())) return true;
} else {
- if (equalsEquals(originalDeclaringClass, currentType.original())) return true;
+ if (TypeBinding.equalsEquals(originalDeclaringClass, currentType.original())) return true;
}
PackageBinding currentPackage = currentType.fPackage;
// package could be null for wildcards/intersection types, ignore and recurse in superclass
@@ -882,6 +883,10 @@ public void computeId() {
if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ANNOTATION_RETENTION[3]))
this.id = TypeIds.T_JavaLangAnnotationRetention;
return;
+ case 10 :
+ if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ANNOTATION_REPEATABLE[3]))
+ this.id = TypeIds.T_JavaLangAnnotationRepeatable;
+ return;
case 15 :
if (CharOperation.equals(typeName, TypeConstants.JAVA_LANG_ANNOTATION_RETENTIONPOLICY[3]))
this.id = TypeIds.T_JavaLangAnnotationRetentionPolicy;
@@ -1598,7 +1603,7 @@ public void resetIncompatibleTypes() {
//{ObjectTeams: new parameter useObjectShortcut
private boolean isCompatibleWith0(TypeBinding otherType, boolean useObjectShortcut, /*@Nullable*/ Scope captureScope) {
// SH}
- if (otherType == this)
+ if (TypeBinding.equalsEquals(otherType, this))
return true;
//{ObjectTeams: respect new param:
/*orig:
@@ -1635,7 +1640,7 @@ private boolean isCompatibleWith0(TypeBinding otherType, boolean useObjectShortc
case Binding.GENERIC_TYPE :
case Binding.PARAMETERIZED_TYPE :
case Binding.RAW_TYPE :
- if (erasure() == otherType.erasure())
+ if (TypeBinding.equalsEquals(erasure(), otherType.erasure()))
return false; // should have passed equivalence check
// above if same erasure
}
@@ -1765,6 +1770,13 @@ public final boolean isPublic() {
}
/**
+ * Answer true if the receiver is an annotation which may be repeatable. Overridden as appropriate.
+ */
+public boolean isRepeatableAnnotation() {
+ return false;
+}
+
+/**
* Answer true if the receiver is a static member type (or toplevel)
*/
public final boolean isStatic() {
@@ -1928,6 +1940,10 @@ public char[] readableName() /*java.lang.Object, p.X<T> */ {
return readableName;
}
+public ReferenceBinding resolveContainerAnnotation() {
+ return null;
+}
+
protected void appendNullAnnotation(StringBuffer nameBuffer, CompilerOptions options) {
if (options.isAnnotationBasedNullAnalysisEnabled) {
// restore applied null annotation from tagBits:
@@ -1957,6 +1973,9 @@ AnnotationBinding[] retrieveAnnotations(Binding binding) {
public void setAnnotations(AnnotationBinding[] annotations) {
storeAnnotations(this, annotations);
}
+public void setContainingAnnotation(ReferenceBinding value) {
+ // Leave this to subclasses
+}
/**
* @see org.eclipse.jdt.internal.compiler.lookup.TypeBinding#nullAnnotatedReadableName(CompilerOptions,boolean)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
index 64d023834..50b9573e6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java
@@ -491,13 +491,13 @@ public abstract class Scope {
substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
if (isMemberTypeOfRaw(originalType, substitutedEnclosing))
return originalParameterizedType.environment.createRawType(
- originalParameterizedType.genericType(), substitutedEnclosing);
+ originalParameterizedType.genericType(), substitutedEnclosing, originalType.getTypeAnnotations());
}
TypeBinding[] originalArguments = originalParameterizedType.arguments;
TypeBinding[] substitutedArguments = originalArguments;
if (originalArguments != null) {
if (substitution.isRawSubstitution()) {
- return originalParameterizedType.environment.createRawType(originalParameterizedType.genericType(), substitutedEnclosing);
+ return originalParameterizedType.environment.createRawType(originalParameterizedType.genericType(), substitutedEnclosing, originalType.getTypeAnnotations());
}
substitutedArguments = substitute(substitution, originalArguments);
}
@@ -510,16 +510,16 @@ public abstract class Scope {
}
// SH}
return originalParameterizedType.environment.createParameterizedType(
- originalParameterizedType.genericType(), substitutedArguments, substitutedEnclosing);
+ originalParameterizedType.genericType(), substitutedArguments, substitutedEnclosing, originalType.getTypeAnnotations());
}
break;
case Binding.ARRAY_TYPE:
ArrayBinding originalArrayType = (ArrayBinding) originalType;
TypeBinding originalLeafComponentType = originalArrayType.leafComponentType;
- TypeBinding substitute = substitute(substitution, originalLeafComponentType); // substitute could itself be array type
+ TypeBinding substitute = substitute(substitution, originalLeafComponentType); // substitute could itself be array type, TODO(Srikanth): need a test case.
if (substitute != originalLeafComponentType) {
- return originalArrayType.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions());
+ return originalArrayType.environment.createArrayType(substitute.leafComponentType(), substitute.dimensions() + originalType.dimensions(), originalType.getTypeAnnotations());
}
break;
@@ -550,7 +550,7 @@ public abstract class Scope {
}
}
}
- return wildcard.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, substitutedOtherBounds, wildcard.boundKind);
+ return wildcard.environment.createWildcard(wildcard.genericType, wildcard.rank, substitutedBound, substitutedOtherBounds, wildcard.boundKind, wildcard.getTypeAnnotations());
}
}
break;
@@ -563,14 +563,14 @@ public abstract class Scope {
if (originalEnclosing != null) {
substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
if (isMemberTypeOfRaw(originalType, substitutedEnclosing))
- return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing);
+ return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations());
}
// treat as if parameterized with its type variables (non generic type gets 'null' arguments)
if (substitutedEnclosing != originalEnclosing) {
return substitution.isRawSubstitution()
- ? substitution.environment().createRawType(originalReferenceType, substitutedEnclosing)
- : substitution.environment().createParameterizedType(originalReferenceType, null, substitutedEnclosing);
+ ? substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations())
+ : substitution.environment().createParameterizedType(originalReferenceType, null, substitutedEnclosing, originalType.getTypeAnnotations());
}
break;
case Binding.GENERIC_TYPE:
@@ -580,16 +580,16 @@ public abstract class Scope {
if (originalEnclosing != null) {
substitutedEnclosing = (ReferenceBinding) substitute(substitution, originalEnclosing);
if (isMemberTypeOfRaw(originalType, substitutedEnclosing))
- return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing);
+ return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations());
}
if (substitution.isRawSubstitution()) {
- return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing);
+ return substitution.environment().createRawType(originalReferenceType, substitutedEnclosing, originalType.getTypeAnnotations());
}
// treat as if parameterized with its type variables (non generic type gets 'null' arguments)
originalArguments = originalReferenceType.typeVariables();
substitutedArguments = substitute(substitution, originalArguments);
- return substitution.environment().createParameterizedType(originalReferenceType, substitutedArguments, substitutedEnclosing);
+ return substitution.environment().createParameterizedType(originalReferenceType, substitutedArguments, substitutedEnclosing, originalType.getTypeAnnotations());
}
return originalType;
}
@@ -798,10 +798,10 @@ public abstract class Scope {
TypeVariableBinding typeVariable = typeParameter.binding;
if (typeVariable == null) return false;
- typeVariable.superclass = getJavaLangObject();
- typeVariable.superInterfaces = Binding.NO_SUPERINTERFACES;
+ typeVariable.setSuperClass(getJavaLangObject());
+ typeVariable.setSuperInterfaces(Binding.NO_SUPERINTERFACES);
// set firstBound to the binding of the first explicit bound in parameter declaration
- typeVariable.firstBound = null; // first bound used to compute erasure
+ typeVariable.setFirstBound(null); // first bound used to compute erasure
}
nextVariable: for (int i = 0; i < paramLength; i++) {
TypeParameter typeParameter = typeParameters[i];
@@ -883,12 +883,12 @@ public abstract class Scope {
} else
// SH}
if (!superType.isInterface()) {
- typeVariable.superclass = superRefType;
+ typeVariable.setSuperClass(superRefType);
} else {
- typeVariable.superInterfaces = new ReferenceBinding[] {superRefType};
+ typeVariable.setSuperInterfaces(new ReferenceBinding[] {superRefType});
}
typeVariable.tagBits |= superType.tagBits & TagBits.ContainsNestedTypeReferences;
- typeVariable.firstBound = superRefType; // first bound used to compute erasure
+ typeVariable.setFirstBound(superRefType); // first bound used to compute erasure
}
}
TypeReference[] boundRefs = typeParameter.bounds;
@@ -946,7 +946,7 @@ public abstract class Scope {
}
}
int size = typeVariable.superInterfaces.length;
- System.arraycopy(typeVariable.superInterfaces, 0, typeVariable.superInterfaces = new ReferenceBinding[size + 1], 0, size);
+ System.arraycopy(typeVariable.superInterfaces, 0, typeVariable.setSuperInterfaces(new ReferenceBinding[size + 1]), 0, size);
typeVariable.superInterfaces[size] = superRefType;
}
}
@@ -961,8 +961,12 @@ public abstract class Scope {
}
public ArrayBinding createArrayType(TypeBinding type, int dimension) {
+ return createArrayType(type, dimension, Binding.NO_ANNOTATIONS);
+ }
+
+ public ArrayBinding createArrayType(TypeBinding type, int dimension, AnnotationBinding[] annotations) {
if (type.isValidBinding())
- return environment().createArrayType(type, dimension);
+ return environment().createArrayType(type, dimension, annotations);
// do not cache obvious invalid types
return new ArrayBinding(type, dimension, environment());
}
@@ -4921,25 +4925,27 @@ public abstract class Scope {
TypeBinding substitutedSuperclass = Scope.substitute(substitution, originalVariable.superclass);
ReferenceBinding[] substitutedInterfaces = Scope.substitute(substitution, originalVariable.superInterfaces);
if (originalVariable.firstBound != null) {
- substitutedVariable.firstBound = originalVariable.firstBound == originalVariable.superclass
+ TypeBinding firstBound;
+ firstBound = originalVariable.firstBound == originalVariable.superclass
? substitutedSuperclass // could be array type or interface
: substitutedInterfaces[0];
+ substitutedVariable.setFirstBound(firstBound);
}
switch (substitutedSuperclass.kind()) {
case Binding.ARRAY_TYPE :
- substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
- substitutedVariable.superInterfaces = substitutedInterfaces;
+ substitutedVariable.setSuperClass(environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null));
+ substitutedVariable.setSuperInterfaces(substitutedInterfaces);
break;
default:
if (substitutedSuperclass.isInterface()) {
- substitutedVariable.superclass = environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null);
+ substitutedVariable.setSuperClass(environment.getResolvedType(TypeConstants.JAVA_LANG_OBJECT, null));
int interfaceCount = substitutedInterfaces.length;
System.arraycopy(substitutedInterfaces, 0, substitutedInterfaces = new ReferenceBinding[interfaceCount+1], 1, interfaceCount);
substitutedInterfaces[0] = (ReferenceBinding) substitutedSuperclass;
- substitutedVariable.superInterfaces = substitutedInterfaces;
+ substitutedVariable.setSuperInterfaces(substitutedInterfaces);
} else {
- substitutedVariable.superclass = (ReferenceBinding) substitutedSuperclass; // typeVar was extending other typeVar which got substituted with interface
- substitutedVariable.superInterfaces = substitutedInterfaces;
+ substitutedVariable.setSuperClass((ReferenceBinding) substitutedSuperclass); // typeVar was extending other typeVar which got substituted with interface
+ substitutedVariable.setSuperInterfaces(substitutedInterfaces);
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 8247e9771..3e1149edd 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -33,6 +33,9 @@
* Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
* Bug 415850 - [1.8] Ensure RunJDTCoreTests can cope with null annotations enabled
* Bug 416172 - [1.8][compiler][null] null type annotation not evaluated on method return type
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
+ * Jesper S Moller <jesper@selskabet.org> - Contributions for
+ * Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -115,18 +118,19 @@ import org.eclipse.objectteams.otdt.internal.core.compiler.util.TypeAnalyzer;
*/
@SuppressWarnings("unchecked")
public class SourceTypeBinding extends ReferenceBinding {
- public ReferenceBinding superclass;
- public ReferenceBinding[] superInterfaces;
- private FieldBinding[] fields;
- private MethodBinding[] methods;
- public ReferenceBinding[] memberTypes;
+ public ReferenceBinding superclass; // MUST NOT be modified directly, use setter !
+ public ReferenceBinding[] superInterfaces; // MUST NOT be modified directly, use setter !
+ private FieldBinding[] fields; // MUST NOT be modified directly, use setter !
+ private MethodBinding[] methods; // MUST NOT be modified directly, use setter !
+ public ReferenceBinding[] memberTypes; // MUST NOT be modified directly, use setter !
//{ObjectTeams: initialization added
// readableName() will otherwise not work before Scope.buildTypeVariables()!
- public TypeVariableBinding[] typeVariables = Binding.NO_TYPE_VARIABLES;
+ public TypeVariableBinding[] typeVariables = Binding.NO_TYPE_VARIABLES; // MUST NOT be modified directly, use setter !
// SH}
public ClassScope scope;
protected SourceTypeBinding prototype;
+ LookupEnvironment environment;
// Synthetics are separated into 4 categories: methods, super methods, fields, class literals and bridge methods
// if a new category is added, also increment MAX_SYNTHETICS
@@ -154,12 +158,13 @@ public class SourceTypeBinding extends ReferenceBinding {
protected SourceTypeBinding() { super(); } // default ctor for Singleton membertypes NoBaseclass, ProblemBaseclass
//Markus Witte}
-
+
private SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder
private int defaultNullness;
private int nullnessDefaultInitialized = 0; // 0: nothing; 1: type; 2: package
private int lambdaOrdinal = 0;
+ private ReferenceBinding containingAnnotation = null;
public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
//{ObjectTeams: // share model from TypeDeclaration:
@@ -177,6 +182,7 @@ public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassSc
// SH}
this.sourceName = scope.referenceContext.name;
this.scope = scope;
+ this.environment = scope.environment();
//{ObjectTeams: ROFI create a package binding for our role files (if any):
maybeSetTeamPackage(compoundName, fPackage, scope.environment());
// SH}
@@ -190,19 +196,18 @@ public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassSc
public SourceTypeBinding(SourceTypeBinding prototype) {
super(prototype);
+
this.prototype = prototype.prototype;
- this.compoundName = prototype.compoundName;
- this.fPackage = prototype.fPackage;
- this.fileName = prototype.fileName;
- this.modifiers = prototype.modifiers;
- this.sourceName = prototype.sourceName;
-
+ this.prototype.tagBits |= TagBits.HasAnnotatedVariants;
+ this.tagBits &= ~TagBits.HasAnnotatedVariants;
+
this.superclass = prototype.superclass;
this.superInterfaces = prototype.superInterfaces;
this.fields = prototype.fields;
this.methods = prototype.methods;
this.memberTypes = prototype.memberTypes;
this.typeVariables = prototype.typeVariables;
+ this.environment = prototype.environment;
// this.scope = prototype.scope; // Will defeat CompilationUnitDeclaration.cleanUp(TypeDeclaration) && CompilationUnitDeclaration.cleanUp(), so not copied, not an issue for JSR 308.
@@ -212,6 +217,8 @@ public SourceTypeBinding(SourceTypeBinding prototype) {
this.defaultNullness = prototype.defaultNullness;
this.nullnessDefaultInitialized= prototype.nullnessDefaultInitialized;
this.lambdaOrdinal = prototype.lambdaOrdinal;
+ this.containingAnnotation = prototype.containingAnnotation;
+ this.tagBits |= TagBits.HasUnresolvedMemberTypes; // see memberTypes()
//{ObjectTeams: team?
if (prototype._teamModel != null)
@@ -220,6 +227,9 @@ public SourceTypeBinding(SourceTypeBinding prototype) {
}
private void addDefaultAbstractMethods() {
+
+ if (this != this.prototype) throw new IllegalStateException();
+
if ((this.tagBits & TagBits.KnowsDefaultAbstractMethods) != 0) return;
this.tagBits |= TagBits.KnowsDefaultAbstractMethods;
@@ -279,7 +289,7 @@ private void addDefaultAbstractMethods() {
}
if (defaultAbstractsCount > 0) {
int length = this.methods.length;
- System.arraycopy(this.methods, 0, this.methods = new MethodBinding[length + defaultAbstractsCount], 0, length);
+ System.arraycopy(this.methods, 0, setMethods(new MethodBinding[length + defaultAbstractsCount]), 0, length);
System.arraycopy(defaultAbstracts, 0, this.methods, length, defaultAbstractsCount);
// re-sort methods
length = length + defaultAbstractsCount;
@@ -294,6 +304,9 @@ private void addDefaultAbstractMethods() {
* Answer the new field or the existing field if one already existed.
*/
public FieldBinding addSyntheticFieldForInnerclass(LocalVariableBinding actualOuterLocalVariable) {
+
+ if (this != this.prototype) throw new IllegalStateException();
+
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
@@ -340,6 +353,9 @@ public FieldBinding addSyntheticFieldForInnerclass(LocalVariableBinding actualOu
* Answer the new field or the existing field if one already existed.
*/
public FieldBinding addSyntheticFieldForInnerclass(ReferenceBinding enclosingType) {
+
+ if (this != this.prototype) throw new IllegalStateException();
+
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
@@ -457,6 +473,9 @@ final public void computeValueParameterSlotSizes() {
* Answer the new field or the existing field if one already existed.
*/
public FieldBinding addSyntheticFieldForClassLiteral(TypeBinding targetType, BlockScope blockScope) {
+
+ if (this != this.prototype) throw new IllegalStateException();
+
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] == null)
@@ -496,6 +515,9 @@ public FieldBinding addSyntheticFieldForClassLiteral(TypeBinding targetType, Blo
* Answer the new field or the existing field if one already existed.
*/
public FieldBinding addSyntheticFieldForAssert(BlockScope blockScope) {
+
+ if (this != this.prototype) throw new IllegalStateException();
+
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
@@ -540,6 +562,8 @@ public FieldBinding addSyntheticFieldForAssert(BlockScope blockScope) {
* Answer the new field or the existing field if one already existed.
*/
public FieldBinding addSyntheticFieldForEnumValues() {
+
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
@@ -616,6 +640,7 @@ public SyntheticMethodBinding addSyntheticMethod(FieldBinding targetField, boole
:giro*/
public SyntheticMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess, boolean isSuperAccess, boolean externalizedReceiver) {
// SH}
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
@@ -675,6 +700,7 @@ public SyntheticMethodBinding addSyntheticMethod(FieldBinding targetField, boole
* char[] constants from TypeConstants must be used: TypeConstants.VALUES/VALUEOF
*/
public SyntheticMethodBinding addSyntheticEnumMethod(char[] selector) {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
@@ -698,6 +724,7 @@ public SyntheticMethodBinding addSyntheticEnumMethod(char[] selector) {
* Add a synthetic field to handle the cache of the switch translation table for the corresponding enum type
*/
public SyntheticFieldBinding addSyntheticFieldForSwitchEnum(char[] fieldName, String key) {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
@@ -742,6 +769,7 @@ public SyntheticFieldBinding addSyntheticFieldForSwitchEnum(char[] fieldName, St
* char[] constants from TypeConstants must be used: TypeConstants.VALUES/VALUEOF
*/
public SyntheticMethodBinding addSyntheticMethodForSwitchEnum(TypeBinding enumBinding) {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
@@ -769,6 +797,7 @@ public SyntheticMethodBinding addSyntheticMethodForSwitchEnum(TypeBinding enumBi
return accessMethod;
}
public SyntheticMethodBinding addSyntheticMethodForEnumInitialization(int begin, int end) {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
@@ -781,6 +810,7 @@ public SyntheticMethodBinding addSyntheticMethodForEnumInitialization(int begin,
return accessMethod;
}
public SyntheticMethodBinding addSyntheticMethod(LambdaExpression lambda) {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
@@ -811,6 +841,7 @@ public SyntheticMethodBinding addSyntheticMethod(MethodBinding targetMethod, boo
isSuperAccess);
}
// SH}
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
@@ -893,6 +924,7 @@ public SyntheticMethodBinding findOuterRoleMethodSyntheticAccessor(MethodBinding
}
// SH}
public SyntheticMethodBinding addSyntheticArrayMethod(ArrayBinding arrayType, int purpose) {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
@@ -915,6 +947,7 @@ public SyntheticMethodBinding addSyntheticArrayMethod(ArrayBinding arrayType, in
return arrayMethod;
}
public SyntheticMethodBinding addSyntheticFactoryMethod(MethodBinding privateConstructor, MethodBinding publicConstructor, TypeBinding [] enclosingInstances) {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null)
this.synthetics = new HashMap[MAX_SYNTHETICS];
if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
@@ -929,6 +962,7 @@ public SyntheticMethodBinding addSyntheticFactoryMethod(MethodBinding privateCon
* Record the fact that bridge methods need to be generated to override certain inherited methods
*/
public SyntheticMethodBinding addSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge, MethodBinding targetMethod) {
+ if (this != this.prototype) throw new IllegalStateException();
if (isInterface()) return null; // only classes & enums get bridge methods
// targetMethod may be inherited
//{ObjectTeams: retrieve callin method's real return type:
@@ -981,6 +1015,7 @@ public SyntheticMethodBinding addSyntheticBridgeMethod(MethodBinding inheritedMe
* from a non-public class into a public class (only in 1.6 or greater)
*/
public SyntheticMethodBinding addSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge) {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.scope.compilerOptions().complianceLevel <= ClassFileConstants.JDK1_5) {
return null;
}
@@ -1033,11 +1068,13 @@ boolean areMethodsInitialized() {
return this.methods != Binding.UNINITIALIZED_METHODS;
}
public int kind() {
+ if (this != this.prototype)
+ return this.prototype.kind();
if (this.typeVariables != Binding.NO_TYPE_VARIABLES) return Binding.GENERIC_TYPE;
return Binding.TYPE;
}
-public TypeBinding clone(TypeBinding immaterial, TypeBinding[] irrelevant) {
+public TypeBinding clone(TypeBinding immaterial) {
return new SourceTypeBinding(this);
}
@@ -1099,6 +1136,7 @@ public char[] computeUniqueKey(boolean isLeaf) {
public
// SH}
void faultInTypesForFieldsAndMethods() {
+ if (this != this.prototype) throw new IllegalStateException();
// check @Deprecated annotation
getAnnotationTagBits(); // marks as deprecated by side effect
ReferenceBinding enclosingType = enclosingType();
@@ -1121,8 +1159,12 @@ void faultInTypesForFieldsAndMethods() {
// NOTE: the type of each field of a source type is resolved when needed
public FieldBinding[] fields() {
- if (this != this.prototype)
- return this.prototype.fields();
+ if (this != this.prototype) {
+ if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
+ return this.fields;
+ this.tagBits |= TagBits.AreFieldsComplete;
+ return this.fields = this.prototype.fields();
+ }
if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
return this.fields;
@@ -1173,14 +1215,14 @@ public FieldBinding[] fields() {
// ensure fields are consistent reqardless of the error
int newSize = resolvedFields.length - failed;
if (newSize == 0)
- return this.fields = Binding.NO_FIELDS;
+ return setFields(Binding.NO_FIELDS);
FieldBinding[] newFields = new FieldBinding[newSize];
for (int i = 0, j = 0, length = resolvedFields.length; i < length; i++) {
if (resolvedFields[i] != null)
newFields[j++] = resolvedFields[i];
}
- this.fields = newFields;
+ setFields(newFields);
}
}
this.tagBits |= TagBits.AreFieldsComplete;
@@ -1234,6 +1276,8 @@ public char[] genericSignature() {
/**
* Compute the tagbits for standard annotations. For source types, these could require
* lazily resolving corresponding annotation nodes, in case of forward references.
+ * For type use bindings, this method still returns the tagbits corresponding to the type
+ * declaration binding.
* @see org.eclipse.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits()
*/
public long getAnnotationTagBits() {
@@ -1432,6 +1476,7 @@ public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes
//NOTE: the type of a field of a source type is resolved when needed
public FieldBinding getField(char[] fieldName, boolean needResolve) {
+
if (this != this.prototype)
return this.prototype.getField(fieldName, needResolve);
//{ObjectTeams: could be called before fields are present
@@ -1440,7 +1485,7 @@ public FieldBinding getField(char[] fieldName, boolean needResolve) {
if (this.fields == Binding.UNINITIALIZED_FIELDS)
return null;
// SH}
-
+
if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
return ReferenceBinding.binarySearch(fieldName, this.fields);
@@ -1501,7 +1546,7 @@ public FieldBinding getField(char[] fieldName, boolean needResolve) {
// ensure fields are consistent reqardless of the error
int newSize = this.fields.length - 1;
if (newSize == 0) {
- this.fields = Binding.NO_FIELDS;
+ setFields(Binding.NO_FIELDS);
} else {
FieldBinding[] newFields = new FieldBinding[newSize];
int index = 0;
@@ -1510,7 +1555,7 @@ public FieldBinding getField(char[] fieldName, boolean needResolve) {
if (f == field) continue;
newFields[index++] = f;
}
- this.fields = newFields;
+ setFields(newFields);
}
}
}
@@ -1695,6 +1740,7 @@ ReferenceBinding findTypeInTeamPackage(char[] name) {
* or null if one does not exist.
*/
public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null || this.synthetics[SourceTypeBinding.FIELD_EMUL] == null) return null;
return (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(actualOuterLocalVariable);
}
@@ -1726,7 +1772,7 @@ public FieldBinding getSyntheticClassLiteral(char[] fieldName) {
* or null if one does not exist.
*/
public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {
-
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null || this.synthetics[SourceTypeBinding.FIELD_EMUL] == null) return null;
FieldBinding field = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(targetEnclosingType);
if (field != null) return field;
@@ -1749,6 +1795,7 @@ public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, bool
* Answer the bridge method associated for an inherited methods or null if one does not exist
*/
public SyntheticMethodBinding getSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge) {
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null) return null;
if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) return null;
SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(inheritedMethodToBridge);
@@ -1807,6 +1854,11 @@ void initializeForStaticImports() {
}
private void initializeNullDefault() {
+
+ if (this != this.prototype) {
+ this.prototype.initializeNullDefault();
+ return;
+ }
// ensure nullness defaults are initialized at all enclosing levels:
switch (this.nullnessDefaultInitialized) {
case 0:
@@ -1826,7 +1878,7 @@ public boolean isEquivalentTo(TypeBinding otherType) {
if (this != this.prototype)
return this.prototype.isEquivalentTo(otherType);
- if (this == otherType) return true;
+ if (TypeBinding.equalsEquals(this, otherType)) return true;
if (otherType == null) return false;
switch(otherType.kind()) {
@@ -1877,9 +1929,22 @@ public boolean isHierarchyConnected() {
return this.prototype.isHierarchyConnected();
return (this.tagBits & TagBits.EndHierarchyCheck) != 0;
}
+public boolean isRepeatableAnnotation() {
+ if (this != this.prototype) throw new IllegalStateException();
+ return this.containingAnnotation != null;
+}
public ReferenceBinding[] memberTypes() {
- if (this != this.prototype)
- return this.prototype.memberTypes();
+ if (this != this.prototype) {
+ if ((this.tagBits & TagBits.HasUnresolvedMemberTypes) == 0)
+ return this.memberTypes;
+ ReferenceBinding [] members = this.memberTypes = this.prototype.memberTypes();
+ int membersLength = members == null ? 0 : members.length;
+ this.memberTypes = new ReferenceBinding[membersLength];
+ for (int i = 0; i < membersLength; i++) {
+ this.memberTypes[i] = this.environment.createMemberType(members[i], this);
+ }
+ this.tagBits &= ~TagBits.HasUnresolvedMemberTypes;
+ }
return this.memberTypes;
}
@@ -1892,8 +1957,12 @@ public boolean hasMemberTypes() {
// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
public MethodBinding[] methods() {
- if (this != this.prototype)
- return this.prototype.methods();
+ if (this != this.prototype) {
+ if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
+ return this.methods;
+ this.tagBits |= TagBits.AreMethodsComplete;
+ return this.methods = this.prototype.methods();
+ }
if ((this.tagBits & TagBits.AreMethodsComplete) != 0)
return this.methods;
@@ -2115,13 +2184,13 @@ public MethodBinding[] methods() {
if (failed > 0) {
int newSize = resolvedMethods.length - failed;
if (newSize == 0) {
- this.methods = Binding.NO_METHODS;
+ setMethods(Binding.NO_METHODS);
} else {
MethodBinding[] newMethods = new MethodBinding[newSize];
for (int i = 0, j = 0, length = resolvedMethods.length; i < length; i++)
if (resolvedMethods[i] != null)
newMethods[j++] = resolvedMethods[i];
- this.methods = newMethods;
+ setMethods(newMethods);
}
}
@@ -2131,6 +2200,21 @@ public MethodBinding[] methods() {
}
return this.methods;
}
+
+public TypeBinding prototype() {
+ return this.prototype;
+}
+
+public ReferenceBinding resolveContainerAnnotation() {
+
+ if (this != this.prototype) throw new IllegalStateException();
+
+ if (this.containingAnnotation instanceof UnresolvedReferenceBinding) {
+ this.containingAnnotation = (ReferenceBinding)BinaryTypeBinding.resolveType(this.containingAnnotation, this.scope.environment(), false);
+ }
+ return this.containingAnnotation;
+}
+
public FieldBinding resolveTypeFor(FieldBinding field) {
if (this != this.prototype)
@@ -2192,12 +2276,12 @@ public FieldBinding resolveTypeFor(FieldBinding field) {
if (sourceLevel >= ClassFileConstants.JDK1_8) {
AnnotationBinding [] annotations = field.getAnnotations();
if (annotations != null && annotations != Binding.NO_ANNOTATIONS) {
- ASTNode.copySE8AnnotationsToType(initializationScope, field, annotations);
+ ASTNode.copySE8AnnotationsToType(initializationScope, field, fieldDecl.annotations);
}
+ Annotation.isTypeUseCompatible(fieldDecl.type, this.scope, fieldDecl.annotations);
}
// apply null default:
- LookupEnvironment environment = this.scope.environment();
- if (environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
+ if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
// TODO(SH): different strategy for 1.8, or is "repair" below enough?
if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
// enum constants neither have a type declaration nor can they be null
@@ -2422,6 +2506,7 @@ public MethodBinding resolveTypesFor(MethodBinding method, boolean fromSynthetic
if (parameterType != null && !parameterType.isValidBinding() && ((parameterType.tagBits & TagBits.HasMissingType) == 0))
foundArgProblem = true;
// SH}
+
if (parameterType == null) {
foundArgProblem = true;
} else if (parameterType == TypeBinding.VOID) {
@@ -2523,9 +2608,10 @@ public MethodBinding resolveTypesFor(MethodBinding method, boolean fromSynthetic
if (sourceLevel >= ClassFileConstants.JDK1_8) {
AnnotationBinding [] annotations = method.getAnnotations();
if (annotations != null && annotations != Binding.NO_ANNOTATIONS) {
- ASTNode.copySE8AnnotationsToType(methodDecl.scope, method, annotations);
+ ASTNode.copySE8AnnotationsToType(methodDecl.scope, method, methodDecl.annotations);
}
}
+ Annotation.isTypeUseCompatible(returnType, this.scope, methodDecl.annotations);
TypeBinding leafType = methodType.leafComponentType();
if (leafType instanceof ReferenceBinding && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
method.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
@@ -2597,7 +2683,7 @@ public MethodBinding resolveTypesFor(MethodBinding method, boolean fromSynthetic
return method;
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=391108
-private void rejectTypeAnnotatedVoidMethod(AbstractMethodDeclaration methodDecl) {
+private static void rejectTypeAnnotatedVoidMethod(AbstractMethodDeclaration methodDecl) {
Annotation[] annotations = methodDecl.annotations;
int length = annotations == null ? 0 : annotations.length;
for (int i = 0; i < length; i++) {
@@ -2609,7 +2695,11 @@ private void rejectTypeAnnotatedVoidMethod(AbstractMethodDeclaration methodDecl)
}
}
}
+
private void createArgumentBindings(MethodBinding method, CompilerOptions compilerOptions) {
+
+ if (this != this.prototype) throw new IllegalStateException();
+
initializeNullDefault();
AbstractMethodDeclaration methodDecl = method.sourceMethod();
if (methodDecl != null) {
@@ -2624,8 +2714,11 @@ private void createArgumentBindings(MethodBinding method, CompilerOptions compil
}
}
}
+
private void evaluateNullAnnotations(long annotationTagBits) {
+ if (this != this.prototype) throw new IllegalStateException();
+
if (this.nullnessDefaultInitialized > 0 || !this.scope.compilerOptions().isAnnotationBasedNullAnalysisEnabled)
return;
boolean isPackageInfo = CharOperation.equals(this.sourceName, TypeConstants.PACKAGE_INFO_NAME);
@@ -2672,10 +2765,9 @@ private void evaluateNullAnnotations(long annotationTagBits) {
}
protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation[] annotations, long annotationTagBits) {
- if (this != this.prototype) {
- this.prototype.checkRedundantNullnessDefaultRecurse(location, annotations, annotationTagBits);
- return;
- }
+
+ if (this != this.prototype) throw new IllegalStateException();
+
if (this.fPackage.defaultNullness != NO_NULL_DEFAULT) {
if ((this.fPackage.defaultNullness == NONNULL_BY_DEFAULT
&& ((annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0))) {
@@ -2687,9 +2779,9 @@ protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation
// return: should caller continue searching?
protected boolean checkRedundantNullnessDefaultOne(ASTNode location, Annotation[] annotations, long annotationTagBits) {
- if (this != this.prototype)
- return this.prototype.checkRedundantNullnessDefaultOne(location, annotations, annotationTagBits);
-
+
+ if (this != this.prototype) throw new IllegalStateException();
+
int thisDefault = this.defaultNullness;
if (thisDefault == NONNULL_BY_DEFAULT) {
if ((annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0) {
@@ -2702,9 +2794,8 @@ protected boolean checkRedundantNullnessDefaultOne(ASTNode location, Annotation[
boolean hasNonNullDefault() {
- if (this != this.prototype)
- return this.prototype.hasNonNullDefault();
-
+ if (this != this.prototype) throw new IllegalStateException();
+
// find the applicable default inside->out:
SourceTypeBinding currentType = null;
@@ -2751,42 +2842,137 @@ private boolean isFirstRoleCtorArg(AbstractMethodDeclaration methodDecl, MethodB
}
// SH}
public AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) {
+ if (this != this.prototype)
+ return this.prototype.retrieveAnnotationHolder(binding, forceInitialization);
if (forceInitialization)
binding.getAnnotationTagBits(); // ensure annotations are up to date
return super.retrieveAnnotationHolder(binding, false);
}
-public void setFields(FieldBinding[] fields) {
- this.fields = fields;
+
+public void setContainingAnnotation(ReferenceBinding value) {
+ if (this != this.prototype) throw new IllegalStateException();
+ this.containingAnnotation = value;
+}
+
+// Propagate writes to all annotated variants so the clones evolve along.
+public FieldBinding [] setFields(FieldBinding[] fields) {
+
if (this != this.prototype)
- this.prototype.setFields(fields);
+ return this.prototype.setFields(fields);
+
+ if ((this.tagBits & TagBits.HasAnnotatedVariants) != 0) {
+ TypeBinding [] annotatedTypes = this.scope.environment().getAnnotatedTypes(this);
+ for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) {
+ SourceTypeBinding annotatedType = (SourceTypeBinding) annotatedTypes[i];
+ annotatedType.fields = fields;
+ }
+ }
//{ObjectTeams: // integrate pendingField
if (this.pendingField != null) {
int l= fields.length;
- System.arraycopy(fields, 0, this.fields= new FieldBinding[l+1], 1, l);
- this.fields[0]= this.pendingField;
+ System.arraycopy(fields, 0, fields= new FieldBinding[l+1], 1, l);
+ fields[0]= this.pendingField;
this.pendingField= null;
}
// in case getField() (or similar func) has already been called reset flag:
this.tagBits &= ~(TagBits.AreFieldsSorted | TagBits.AreFieldsComplete);
// SH}
+ return this.fields = fields;
}
-public void setMethods(MethodBinding[] methods) {
+
+// We need to specialize member types, can't just propagate. Can't specialize here, clones could created post setMemberTypes()
+public ReferenceBinding [] setMemberTypes(ReferenceBinding[] memberTypes) {
+
+ if (this != this.prototype)
+ return this.prototype.setMemberTypes(memberTypes);
+
+ this.memberTypes = memberTypes;
+ if ((this.tagBits & TagBits.HasAnnotatedVariants) != 0) {
+ TypeBinding [] annotatedTypes = this.scope.environment().getAnnotatedTypes(this);
+ for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) {
+ SourceTypeBinding annotatedType = (SourceTypeBinding) annotatedTypes[i];
+ annotatedType.tagBits |= TagBits.HasUnresolvedMemberTypes;
+ annotatedType.memberTypes(); // recompute.
+ }
+ }
+ return this.memberTypes;
+}
+
+// Propagate writes to all annotated variants so the clones evolve along.
+public MethodBinding [] setMethods(MethodBinding[] methods) {
+
+ if (this != this.prototype)
+ return this.prototype.setMethods(methods);
+
+ if ((this.tagBits & TagBits.HasAnnotatedVariants) != 0) {
+ TypeBinding [] annotatedTypes = this.scope.environment().getAnnotatedTypes(this);
+ for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) {
+ SourceTypeBinding annotatedType = (SourceTypeBinding) annotatedTypes[i];
+ annotatedType.methods = methods;
+ }
+ }
//{ObjectTeams: baseCallSurrogate might be stored before regular methods are created
// happens when binary role with static callin method is loaded before STATE_BINDINGS_COMPLETE
if (this.pendingMethods != null) {
assert (this.tagBits & TagBits.AreMethodsSorted) == 0 : "setMethods after sorting"; //$NON-NLS-1$
int len1 = this.pendingMethods.size();
int len2 = methods.length;
- this.methods = new MethodBinding[len1+len2];
+ System.arraycopy(methods, 0, methods=new MethodBinding[len1+len2], len1, len2);
this.pendingMethods.toArray(this.methods);
- System.arraycopy(methods, 0, this.methods, len1, len2);
this.pendingMethods = null;
- } else
+ }
// SH}
- this.methods = methods;
+ return this.methods = methods;
+}
+
+// Propagate writes to all annotated variants so the clones evolve along.
+public ReferenceBinding setSuperClass(ReferenceBinding superClass) {
+
if (this != this.prototype)
- this.prototype.setMethods(methods);
+ return this.prototype.setSuperClass(superClass);
+
+ if ((this.tagBits & TagBits.HasAnnotatedVariants) != 0) {
+ TypeBinding [] annotatedTypes = this.scope.environment().getAnnotatedTypes(this);
+ for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) {
+ SourceTypeBinding annotatedType = (SourceTypeBinding) annotatedTypes[i];
+ annotatedType.superclass = superClass;
+ }
+ }
+ return this.superclass = superClass;
}
+
+// Propagate writes to all annotated variants so the clones evolve along.
+public ReferenceBinding [] setSuperInterfaces(ReferenceBinding [] superInterfaces) {
+
+ if (this != this.prototype)
+ return this.prototype.setSuperInterfaces(superInterfaces);
+
+ if ((this.tagBits & TagBits.HasAnnotatedVariants) != 0) {
+ TypeBinding [] annotatedTypes = this.scope.environment().getAnnotatedTypes(this);
+ for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) {
+ SourceTypeBinding annotatedType = (SourceTypeBinding) annotatedTypes[i];
+ annotatedType.superInterfaces = superInterfaces;
+ }
+ }
+ return this.superInterfaces = superInterfaces;
+}
+
+// Propagate writes to all annotated variants so the clones evolve along.
+public TypeVariableBinding [] setTypeVariables(TypeVariableBinding [] typeVariables) {
+
+ if (this != this.prototype)
+ return this.prototype.setTypeVariables(typeVariables);
+
+ if ((this.tagBits & TagBits.HasAnnotatedVariants) != 0) {
+ TypeBinding [] annotatedTypes = this.scope.environment().getAnnotatedTypes(this);
+ for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) {
+ SourceTypeBinding annotatedType = (SourceTypeBinding) annotatedTypes[i];
+ annotatedType.typeVariables = typeVariables;
+ }
+ }
+ return this.typeVariables = typeVariables;
+}
+
//{ObjectTeams: adding generated elements
FieldBinding pendingField= null;
public void addField(FieldBinding fieldBinding) {
@@ -2966,6 +3152,7 @@ public void resolveGeneratedMethod(AbstractMethodDeclaration methodDeclaration,
public final int sourceEnd() {
if (this != this.prototype)
return this.prototype.sourceEnd();
+
return this.scope.referenceContext.sourceEnd;
}
public final int sourceStart() {
@@ -2984,21 +3171,29 @@ SimpleLookupTable storedAnnotations(boolean forceInitialize) {
//{ObjectTeams: do support annotations for roles for the sake of copying:
if (!this.isRole())
// SH}
- if (!globalOptions.storeAnnotations && !globalOptions.isAnnotationBasedNullAnalysisEnabled)
+ if (!globalOptions.storeAnnotations)
return null; // not supported during this compile
this.storedAnnotations = new SimpleLookupTable(3);
}
return this.storedAnnotations;
}
+
public ReferenceBinding superclass() {
+ if (this != this.prototype)
+ return this.superclass = this.prototype.superclass();
return this.superclass;
}
+
public ReferenceBinding[] superInterfaces() {
+ if (this != this.prototype)
+ return this.superInterfaces = this.prototype.superInterfaces();
return this.superInterfaces;
}
+
public SyntheticMethodBinding[] syntheticMethods() {
- if (this != this.prototype)
- return this.prototype.syntheticMethods();
+
+ if (this != this.prototype) throw new IllegalStateException();
+
//{ObjectTeams: two different kinds of synthetics:
/* orig:
if (this.synthetics == null
@@ -3028,8 +3223,8 @@ public SyntheticMethodBinding[] syntheticMethods() {
}
}
}
- }
// :giro
+ }
// more synthetics to generate:
if (this.synthetics[SourceTypeBinding.ROLE_BRIDGE] != null && this.synthetics[SourceTypeBinding.ROLE_BRIDGE].size() > 0)
{
@@ -3060,8 +3255,8 @@ public SyntheticMethodBinding[] syntheticMethods() {
* Answer the collection of synthetic fields to append into the classfile
*/
public FieldBinding[] syntheticFields() {
- if (this != this.prototype)
- return this.prototype.syntheticFields();
+
+ if (this != this.prototype) throw new IllegalStateException();
if (this.synthetics == null) return null;
int fieldSize = this.synthetics[SourceTypeBinding.FIELD_EMUL] == null ? 0 : this.synthetics[SourceTypeBinding.FIELD_EMUL].size();
@@ -3194,13 +3389,14 @@ public String toString() {
return buffer.toString();
}
public TypeVariableBinding[] typeVariables() {
+ if (this != this.prototype)
+ return this.typeVariables = this.prototype.typeVariables();
return this.typeVariables != null ? this.typeVariables : Binding.NO_TYPE_VARIABLES;
}
void verifyMethods(MethodVerifier verifier) {
- if (this != this.prototype) {
- this.prototype.verifyMethods(verifier);
- return;
- }
+
+ if (this != this.prototype) throw new IllegalStateException();
+
//{ObjectTeams: shortcut for predefined confined types (override final methods???)
if (TypeAnalyzer.isTopConfined(this))
return;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
index beda54550..6fc901aa2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
@@ -96,14 +96,16 @@ public interface TagBits {
long PassedBoundCheck = ASTNode.Bit23;
// set for parameterized type NOT of the form X<?,?>
- long IsBoundParameterizedType = ASTNode.Bit24;
+ long IsBoundParameterizedType = ASTNode.Bit24; // PTB only.
+
+ long HasAnnotatedVariants = ASTNode.Bit24; // TVB, STB
// used by BinaryTypeBinding
long HasUnresolvedTypeVariables = ASTNode.Bit25;
long HasUnresolvedSuperclass = ASTNode.Bit26;
long HasUnresolvedSuperinterfaces = ASTNode.Bit27;
long HasUnresolvedEnclosingType = ASTNode.Bit28;
- long HasUnresolvedMemberTypes = ASTNode.Bit29;
+ long HasUnresolvedMemberTypes = ASTNode.Bit29; // Also in use at STB.
long HasTypeVariable = ASTNode.Bit30; // set either for type variables (direct) or parameterized types indirectly referencing type variables
long HasDirectWildcard = ASTNode.Bit31; // set for parameterized types directly referencing wildcards
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
index d2587b623..199ce238e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
@@ -20,6 +20,7 @@
* bug 392384 - [1.8][compiler][null] Restore nullness info from type annotations in class files
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
* Bug 415291 - [1.8][null] differentiate type incompatibilities due to null annotations
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Jesper S Moller <jesper@selskabet.org> - Contributions for
* bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
*******************************************************************************/
@@ -105,7 +106,6 @@ public TypeBinding() {
public TypeBinding(TypeBinding prototype) { // faithfully copy all instance state - clone operation should specialize/override suitably.
this.id = prototype.id;
this.tagBits = prototype.tagBits;
- this.typeAnnotations = prototype.typeAnnotations;
}
/**
@@ -221,7 +221,7 @@ public void collectSubstitutes(Scope scope, TypeBinding actualType, InferenceCon
make sense for every type in the hierarchy, in which case they are silently ignored. A type may
choose to retain a copy of the prototype for reference.
*/
-public TypeBinding clone(TypeBinding enclosingType, TypeBinding[] typeArguments) {
+public TypeBinding clone(TypeBinding enclosingType) {
throw new IllegalStateException("TypeBinding#clone() should have been overridden"); //$NON-NLS-1$
}
@@ -247,7 +247,7 @@ public int depth() {
return 0;
}
-/* Answer the receiver's enclosing type... null if the receiver is a top level type.
+/* Answer the receiver's enclosing type... null if the receiver is a top level type or is an array or a non reference type.
*/
public ReferenceBinding enclosingType() {
return null;
@@ -518,10 +518,6 @@ void initializeForStaticImports() {
// only applicable to source types
}
-public boolean isAnnotationType() {
- return false;
-}
-
public final boolean isAnonymousType() {
return (this.tagBits & TagBits.IsAnonymousType) != 0;
}
@@ -1084,6 +1080,13 @@ public boolean isReifiable() {
}
/**
+ * Answer true if the receiver is a static member type (or toplevel)
+ */
+public boolean isStatic() {
+ return false;
+}
+
+/**
* Returns true if a given type may be thrown
*/
public boolean isThrowable() {
@@ -1093,13 +1096,13 @@ public boolean isThrowable() {
public boolean isTypeArgumentContainedBy(TypeBinding otherType) {
//{ObjectTeams: only slightly weaker form of identity:
/* orig:
- if (this == otherType)
+ if (TypeBinding.equalsEquals(this, otherType))
:giro */
if (RoleTypeBinding.eq(this, otherType))
// SH}
return true;
switch (otherType.kind()) {
- // handle captured wildcards.
+ // handle captured wildcards.
case Binding.TYPE_PARAMETER: {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=347426
if (!isParameterizedType() || !otherType.isCapture()) {
@@ -1168,7 +1171,7 @@ public boolean isTypeArgumentContainedBy(TypeBinding otherType) {
TypeBinding otherBound = otherWildcard.bound;
switch (otherWildcard.boundKind) {
case Wildcard.EXTENDS:
- if (otherBound == this)
+ if (TypeBinding.equalsEquals(otherBound, this))
return true; // ? extends T <= ? extends ? extends T
if (upperBound == null)
return false;
@@ -1403,13 +1406,13 @@ public abstract char[] qualifiedSourceName();
/**
* @return the JSR 308 annotations for this type.
*/
-public AnnotationBinding[] getTypeAnnotations() {
+final public AnnotationBinding[] getTypeAnnotations() {
return this.typeAnnotations;
}
public void setTypeAnnotations(AnnotationBinding[] annotations, boolean evalNullAnnotations) {
this.tagBits |= TagBits.HasTypeAnnotations;
- if (annotations == null || annotations == Binding.NO_ANNOTATIONS)
+ if (annotations == null || annotations.length == 0)
return;
this.typeAnnotations = annotations;
if (evalNullAnnotations) {
@@ -1426,6 +1429,7 @@ public void setTypeAnnotations(AnnotationBinding[] annotations, boolean evalNull
}
}
}
+ // we do accept contradictory tagBits here, to support detecting contradictions caused by type substitution
}
}
@@ -1511,5 +1515,16 @@ public static boolean notEquals(TypeBinding that, TypeBinding other) {
return false;
return true;
}
+/** Return the primordial type from which the receiver was cloned. Not all types track a prototype, only {@link SourceTypeBinding},
+ * {@link BinaryTypeBinding} and {@link UnresolvedReferenceBinding} do so as of now. In fact some types e.g {@link ParameterizedTypeBinding}
+ * should not do so. Deflecting a query to a prototype would lead to wrong results in the case of {@link ParameterizedTypeBinding}
+ */
+public TypeBinding prototype() {
+ return null;
+}
+
+public boolean isUnresolvedType() {
+ return false;
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
index 938630af4..a33464c45 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
@@ -18,9 +18,9 @@
* bug 400421 - [compiler] Null analysis for fields does not take @com.google.inject.Inject into account
* bug 382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions
* Bug 405569 - Resource leak check false positive when using DbUtils.closeQuietly
- *
* Jesper S Moller - Contributions for
- * Bug 405066 - [1.8][compiler][codegen] Implement code generation infrastructure for JSR335
+ * Bug 405066 - [1.8][compiler][codegen] Implement code generation infrastructure for JSR335
+ * Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -147,6 +147,7 @@ public interface TypeConstants {
char[][] JAVA_LANG_DEPRECATED = {JAVA, LANG, "Deprecated".toCharArray()}; //$NON-NLS-1$
char[][] JAVA_LANG_ANNOTATION_DOCUMENTED = {JAVA, LANG, ANNOTATION, "Documented".toCharArray()}; //$NON-NLS-1$
char[][] JAVA_LANG_ANNOTATION_INHERITED = {JAVA, LANG, ANNOTATION, "Inherited".toCharArray()}; //$NON-NLS-1$
+ char[][] JAVA_LANG_ANNOTATION_REPEATABLE = {JAVA, LANG, ANNOTATION, "Repeatable".toCharArray()}; //$NON-NLS-1$
char[][] JAVA_LANG_OVERRIDE = {JAVA, LANG, "Override".toCharArray()}; //$NON-NLS-1$
char[][] JAVA_LANG_FUNCTIONAL_INTERFACE = {JAVA, LANG, "FunctionalInterface".toCharArray()}; //$NON-NLS-1$
char[][] JAVA_LANG_ANNOTATION_RETENTION = {JAVA, LANG, ANNOTATION, "Retention".toCharArray()}; //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
index 2f4428ff0..66b0dc365 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
@@ -18,6 +18,8 @@
* bug 358903 - Filter practically unimportant resource leak warnings
* bug 400421 - [compiler] Null analysis for fields does not take @com.google.inject.Inject into account
* bug 382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions
+ * Jesper S Moller <jesper@selskabet.org> - Contributions for
+ * Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -124,13 +126,14 @@ public interface TypeIds {
final int T_JavaUtilObjects = 74;
// java 8
- final int T_JavaLangFunctionalInterface = 69;
+ final int T_JavaLangFunctionalInterface = 77;
// new in 3.9 to identify known @Inject annotations
final int T_JavaxInjectInject = 80;
final int T_ComGoogleInjectInject = 81;
+ // Java 8 - JEP 120
+ final int T_JavaLangAnnotationRepeatable = 90;
// If you add new type id, make sure to bump up T_LastWellKnownTypeId if there is a cross over.
-
final int T_LastWellKnownTypeId = 128;
final int NoId = Integer.MAX_VALUE;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
new file mode 100644
index 000000000..c33f02e30
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeSystem.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 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.internal.compiler.lookup;
+
+import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.ITeamAnchor;
+
+public abstract class TypeSystem {
+
+ public boolean isAnnotatedTypeSystem() {
+ return false;
+ }
+
+ public abstract AnnotationBinding getAnnotationType(ReferenceBinding annotationType, boolean requireResolved);
+
+ public abstract ArrayBinding getArrayType(TypeBinding leafComponentType, int dimensions);
+
+ public ArrayBinding getArrayType(TypeBinding leafComponentType, int dimensions, AnnotationBinding[] annotations) {
+ return getArrayType(leafComponentType, dimensions);
+ }
+//{ObjectTeams: 2 parameters added:
+/* orig:
+ public abstract ParameterizedTypeBinding getParameterizedType (ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType);
+ :giro */
+ public abstract ParameterizedTypeBinding getParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments,
+ ITeamAnchor teamAnchor, int valueParamPosition, ReferenceBinding enclosingType);
+
+/* orig:
+ public ParameterizedTypeBinding getParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType, AnnotationBinding[] annotations) {
+ return getParameterizedType(genericType, typeArguments, enclosingType);
+ :giro */
+ public ParameterizedTypeBinding getParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments,
+ ITeamAnchor teamAnchor, int valueParamPosition, ReferenceBinding enclosingType, AnnotationBinding[] annotations) {
+ return getParameterizedType(genericType, typeArguments, teamAnchor, valueParamPosition, enclosingType);
+// SH}
+ }
+
+ public abstract RawTypeBinding getRawType(ReferenceBinding genericType, ReferenceBinding enclosingType);
+
+ public RawTypeBinding getRawType(ReferenceBinding genericType, ReferenceBinding enclosingType, AnnotationBinding[] annotations) {
+ return getRawType(genericType, enclosingType);
+ }
+
+ public abstract WildcardBinding getWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind);
+
+ public WildcardBinding getWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind, AnnotationBinding[] annotations) {
+ return getWildcard(genericType, rank, bound, otherBounds, boundKind);
+ }
+
+ public TypeBinding getAnnotatedType(TypeBinding type, AnnotationBinding[][] annotations) {
+ return type;
+ }
+
+
+ public abstract void reset();
+
+ public abstract void updateCaches(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType);
+
+ public abstract TypeBinding getUnannotatedType(TypeBinding type);
+
+ // Given a type, return all its variously annotated versions.
+ public TypeBinding[] getAnnotatedTypes(TypeBinding type) {
+ return Binding.NO_TYPES;
+ }
+
+ public ReferenceBinding getMemberType(ReferenceBinding memberType, ReferenceBinding enclosingType) {
+ return memberType; // nothing to do for plain vanilla type system.
+ }
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
index f91b08529..19d334e5f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java
@@ -20,12 +20,14 @@
* bug 395002 - Self bound generic class doesn't resolve bounds properly for wildcards for certain parametrisation.
* bug 392384 - [1.8][compiler][null] Restore nullness info from type annotations in class files
* Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
@@ -48,11 +50,11 @@ public class TypeVariableBinding extends ReferenceBinding {
* Denote the first explicit (binding) bound amongst the supertypes (from declaration in source)
* If no superclass was specified, then it denotes the first superinterface, or null if none was specified.
*/
- public TypeBinding firstBound;
+ public TypeBinding firstBound; // MUST NOT be modified directly, use setter !
// actual resolved variable supertypes (if no superclass bound, then associated to Object)
- public ReferenceBinding superclass;
- public ReferenceBinding[] superInterfaces;
+ public ReferenceBinding superclass; // MUST NOT be modified directly, use setter !
+ public ReferenceBinding[] superInterfaces; // MUST NOT be modified directly, use setter !
//{ObjectTeams: additions:
// bound in <B base R>:
public ReferenceBinding roletype;
@@ -81,6 +83,8 @@ public class TypeVariableBinding extends ReferenceBinding {
this.superInterfaces = prototype.superInterfaces;
this.genericTypeSignature = prototype.genericTypeSignature;
this.environment = prototype.environment;
+ prototype.tagBits |= TagBits.HasAnnotatedVariants;
+ this.tagBits &= ~TagBits.HasAnnotatedVariants;
}
/**
@@ -254,9 +258,9 @@ public class TypeVariableBinding extends ReferenceBinding {
}
}
}
- long nullTagBits = this.tagBits & TagBits.AnnotationNullMASK;
+ long nullTagBits = NullAnnotationMatching.validNullTagBits(this.tagBits);
if (nullTagBits != 0) {
- long argBits = argumentType.tagBits & TagBits.AnnotationNullMASK;
+ long argBits = NullAnnotationMatching.validNullTagBits(argumentType.tagBits);
if (argBits != nullTagBits) {
// System.err.println("TODO(stephan): issue proper error: bound conflict at "+String.valueOf(this.declaringElement.readableName()));
}
@@ -411,12 +415,11 @@ public class TypeVariableBinding extends ReferenceBinding {
return this.superclass.constantPoolName(); // java/lang/Object
}
- public TypeBinding clone(TypeBinding enclosingType, TypeBinding[] typeArguments) {
+ public TypeBinding clone(TypeBinding enclosingType) {
return new TypeVariableBinding(this);
}
public String annotatedDebugName() {
StringBuffer buffer = new StringBuffer(10);
- buffer.append('<');
buffer.append(super.annotatedDebugName());
if (this.superclass != null && this.firstBound == this.superclass) {
buffer.append(" extends ").append(this.superclass.annotatedDebugName()); //$NON-NLS-1$
@@ -432,7 +435,6 @@ public class TypeVariableBinding extends ReferenceBinding {
buffer.append(this.superInterfaces[i].annotatedDebugName());
}
}
- buffer.append('>');
return buffer.toString();
}
/**
@@ -634,7 +636,7 @@ public class TypeVariableBinding extends ReferenceBinding {
// System.err.println("TODO(stephan): report proper error: conflict binary TypeVariable vs. first bound");
}
}
- this.superclass = resolveType;
+ this.setSuperClass(resolveType);
}
ReferenceBinding[] interfaces = this.superInterfaces;
int length;
@@ -657,14 +659,32 @@ public class TypeVariableBinding extends ReferenceBinding {
// refresh the firstBound in case it changed
if (this.firstBound != null) {
if (this.firstBound == oldSuperclass) {
- this.firstBound = this.superclass;
+ this.setFirstBound(this.superclass);
} else if (this.firstBound == oldFirstInterface) {
- this.firstBound = interfaces[0];
+ this.setFirstBound(interfaces[0]);
}
}
this.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
return this;
}
+
+ /* TVB should inherit annotations from declaration site. For example given class X<@NonNull T> { @Readonly T t; },
+ the type of the field t is "@NonNull @Readonly T". This is not true for capture of the wildcard as the wildcard
+ cannot be subsequently referenced by virtue of being anonymous.
+ */
+ public void setTypeAnnotations(AnnotationBinding[] annotations, boolean evalNullAnnotations) {
+ TypeVariableBinding prototype = (TypeVariableBinding) this.environment.getUnannotatedType(this); // also exposes original TVB/capture to type system for id stamping purposes.
+ if (prototype != this && !this.isCapture()) {
+ AnnotationBinding [] declarationAnnotations = prototype.getTypeAnnotations();
+ final int declarationAnnotationsLength = declarationAnnotations == null ? 0 : declarationAnnotations.length;
+ if (declarationAnnotationsLength > 0) {
+ final int annotationsLength = annotations.length;
+ System.arraycopy(annotations, 0, annotations = new AnnotationBinding[annotationsLength + declarationAnnotationsLength], 0, annotationsLength);
+ System.arraycopy(declarationAnnotations, 0, annotations, annotationsLength, declarationAnnotationsLength);
+ }
+ }
+ super.setTypeAnnotations(annotations, evalNullAnnotations);
+ }
/**
* @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#shortReadableName()
*/
@@ -710,6 +730,7 @@ public class TypeVariableBinding extends ReferenceBinding {
return buffer.toString();
}
+ // May still carry declaration site annotations.
public TypeBinding unannotated() {
return this.hasTypeAnnotations() ? this.environment.getUnannotatedType(this) : this;
}
@@ -724,9 +745,9 @@ public class TypeVariableBinding extends ReferenceBinding {
}
public void evaluateNullAnnotations(Scope scope, TypeParameter parameter) {
- long nullTagBits = this.tagBits & TagBits.AnnotationNullMASK;
+ long nullTagBits = NullAnnotationMatching.validNullTagBits(this.tagBits);
if (this.firstBound != null && this.firstBound.isValidBinding()) {
- long superNullTagBits = this.firstBound.tagBits & TagBits.AnnotationNullMASK;
+ long superNullTagBits = NullAnnotationMatching.validNullTagBits(this.firstBound.tagBits);
if (superNullTagBits != 0L) {
if (nullTagBits == 0L) {
nullTagBits |= superNullTagBits;
@@ -744,7 +765,7 @@ public class TypeVariableBinding extends ReferenceBinding {
if ((length = interfaces.length) != 0) {
for (int i = length; --i >= 0;) {
ReferenceBinding resolveType = interfaces[i];
- long superNullTagBits = resolveType.tagBits & TagBits.AnnotationNullMASK;
+ long superNullTagBits = NullAnnotationMatching.validNullTagBits(resolveType.tagBits);
if (superNullTagBits != 0L) {
if (nullTagBits == 0L) {
nullTagBits |= superNullTagBits;
@@ -774,4 +795,47 @@ public class TypeVariableBinding extends ReferenceBinding {
}
return null;
}
+
+ /* An annotated type variable use differs from its declaration exactly in its annotations and in nothing else.
+ Propagate writes to all annotated variants so the clones evolve along.
+ */
+ public TypeBinding setFirstBound(TypeBinding firstBound) {
+ this.firstBound = firstBound;
+ if ((this.tagBits & TagBits.HasAnnotatedVariants) != 0) {
+ TypeBinding [] annotatedTypes = this.environment.getAnnotatedTypes(this);
+ for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) {
+ TypeVariableBinding annotatedType = (TypeVariableBinding) annotatedTypes[i];
+ annotatedType.firstBound = firstBound;
+ }
+ }
+ return firstBound;
+ }
+ /* An annotated type variable use differs from its declaration exactly in its annotations and in nothing else.
+ Propagate writes to all annotated variants so the clones evolve along.
+ */
+ public ReferenceBinding setSuperClass(ReferenceBinding superclass) {
+ this.superclass = superclass;
+ if ((this.tagBits & TagBits.HasAnnotatedVariants) != 0) {
+ TypeBinding [] annotatedTypes = this.environment.getAnnotatedTypes(this);
+ for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) {
+ TypeVariableBinding annotatedType = (TypeVariableBinding) annotatedTypes[i];
+ annotatedType.superclass = superclass;
+ }
+ }
+ return superclass;
+ }
+ /* An annotated type variable use differs from its declaration exactly in its annotations and in nothing else.
+ Propagate writes to all annotated variants so the clones evolve along.
+ */
+ public ReferenceBinding [] setSuperInterfaces(ReferenceBinding[] superInterfaces) {
+ this.superInterfaces = superInterfaces;
+ if ((this.tagBits & TagBits.HasAnnotatedVariants) != 0) {
+ TypeBinding [] annotatedTypes = this.environment.getAnnotatedTypes(this);
+ for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) {
+ TypeVariableBinding annotatedType = (TypeVariableBinding) annotatedTypes[i];
+ annotatedType.superInterfaces = superInterfaces;
+ }
+ }
+ return superInterfaces;
+ }
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnannotatedTypeSystem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnannotatedTypeSystem.java
index 8050a9fb0..b656910a0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnannotatedTypeSystem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnannotatedTypeSystem.java
@@ -32,12 +32,12 @@ import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.RoleTypeBindin
Map<@T4 String, @T5 Object> and @T6 Map<String, Object> and @T7 Map<String, @T8 Object> and Map<String, @T9 Object> would all share the same id since
the unadorned naked type in each case is the same: Map<String, Object>. None of this would share the id with Map<String, String>. Briefly put, if you
take a certain annotated type and strip it of all annotations to come up with the naked type, that naked type and the annotated type would have the
- same id. Alternately, if you take a certain naked type and arrive at the set of all differently annotated types, they would all share the same id while
+ same id. Alternately, if you take a certain naked type and arrive at the universe of all differently annotated types, they would all share the same id while
their bindings could be different - would be different unless they are identically annotated.
Thus subsystems that are annotation agnostic could quickly ascertain binding equality by comparing the id field.
*/
-public class UnannotatedTypeSystem {
+public class UnannotatedTypeSystem extends TypeSystem {
private int typeid = TypeIds.T_LastWellKnownTypeId;
private TypeBinding [][] types;
@@ -51,9 +51,9 @@ public class UnannotatedTypeSystem {
this.types = new TypeBinding[TypeIds.T_LastWellKnownTypeId * 2][];
}
- TypeBinding getUnannotatedType(TypeBinding type) {
+ public TypeBinding getUnannotatedType(TypeBinding type) {
if (type.id == TypeIds.NoId) {
- if (type.hasTypeAnnotations() && !type.isTypeVariable())
+ if (type.hasTypeAnnotations())
throw new IllegalStateException();
int typesLength = this.types.length;
if (this.typeid == typesLength)
@@ -80,6 +80,9 @@ public class UnannotatedTypeSystem {
return this.types[type.id][0] = type;
}
+ /* Note: parameters will not have type type annotations if lookup environment directly uses UTS as its typeSystem. However if this UTS is the underlying type system
+ for an ATS, they may and we need to materialize the unannotated versions and work on them.
+ */
public ArrayBinding getArrayType(TypeBinding leafType, int dimensions) {
TypeBinding unannotatedLeafType = getUnannotatedType(leafType);
TypeBinding[] cachedInfo = this.types[unannotatedLeafType.id]; // by construction, cachedInfo != null now.
@@ -108,6 +111,9 @@ public class UnannotatedTypeSystem {
return (ArrayBinding) (this.types[arrayType.id = this.typeid++][0] = arrayType);
}
+ /* Note: parameters will not have type type annotations if lookup environment directly uses UTS as its typeSystem. However if this UTS is the underlying type system
+ for an ATS, they may and we need to materialize the unannotated versions and work on them.
+ */
//{ObjectTeams: 2 parameters added:
/* orig:
public ParameterizedTypeBinding getParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType) {
@@ -115,7 +121,7 @@ public class UnannotatedTypeSystem {
public ParameterizedTypeBinding getParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments,
ITeamAnchor teamAnchor, int valueParamPosition, ReferenceBinding enclosingType) {
// SH}
- ReferenceBinding unannotatedGenericType = (ReferenceBinding) getUnannotatedType(genericType);
+ ReferenceBinding unannotatedGenericType = (ReferenceBinding) getUnannotatedType(genericType);
int typeArgumentsLength = typeArguments == null ? 0: typeArguments.length;
TypeBinding [] unannotatedTypeArguments = typeArguments == null ? null : new TypeBinding[typeArgumentsLength];
for (int i = 0; i < typeArgumentsLength; i++) {
@@ -193,6 +199,9 @@ public class UnannotatedTypeSystem {
}
//SH}
+ /* Note: parameters will not have type type annotations if lookup environment directly uses UTS as its typeSystem. However if this UTS is the underlying type system
+ for an ATS, they may and we need to materialize the unannotated versions and work on them.
+ */
public RawTypeBinding getRawType(ReferenceBinding genericType, ReferenceBinding enclosingType) {
ReferenceBinding unannotatedGenericType = (ReferenceBinding) getUnannotatedType(genericType);
ReferenceBinding unannotatedEnclosingType = enclosingType == null ? null : (ReferenceBinding) getUnannotatedType(enclosingType);
@@ -223,7 +232,9 @@ public class UnannotatedTypeSystem {
return (RawTypeBinding) (this.types[rawTytpe.id = this.typeid++][0] = rawTytpe);
}
-
+ /* Note: parameters will not have type type annotations if lookup environment directly uses UTS as its typeSystem. However if this UTS is the underlying type system
+ for an ATS, they may and we need to materialize the unannotated versions and work on them.
+ */
public WildcardBinding getWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind) {
if (genericType == null) // pseudo wildcard denoting composite bounds for lub computation
genericType = ReferenceBinding.LUB_GENERIC;
@@ -264,13 +275,20 @@ public class UnannotatedTypeSystem {
return (WildcardBinding) (this.types[wildcard.id = this.typeid++][0] = wildcard);
}
-
- public AnnotationBinding getAnnotationType(ReferenceBinding annotationType) {
+ /* Return a unique annotation binding for an annotation with either no or all default element-value pairs.
+ We may return a resolved annotation when requested for unresolved one, but not vice versa.
+ */
+ public AnnotationBinding getAnnotationType(ReferenceBinding annotationType, boolean requiredResolved) {
AnnotationBinding annotation = (AnnotationBinding) this.annotationTypes.get(annotationType);
if (annotation == null) {
- annotation = new AnnotationBinding(annotationType, Binding.NO_ELEMENT_VALUE_PAIRS);
+ if (requiredResolved)
+ annotation = new AnnotationBinding(annotationType, Binding.NO_ELEMENT_VALUE_PAIRS);
+ else
+ annotation = new UnresolvedAnnotationBinding(annotationType, Binding.NO_ELEMENT_VALUE_PAIRS, this.environment);
this.annotationTypes.put(annotationType, annotation);
}
+ if (requiredResolved)
+ annotation.resolve();
return annotation;
}
@@ -288,5 +306,14 @@ public class UnannotatedTypeSystem {
resolvedType.id = unresolvedTypeId;
this.types[unresolvedTypeId][0] = resolvedType;
}
+ if (this.annotationTypes.get(unresolvedType) != null) { // update the key
+ Object[] keys = this.annotationTypes.keyTable;
+ for (int i = 0, l = keys.length; i < l; i++) {
+ if (keys[i] == unresolvedType) {
+ keys[i] = resolvedType; // hashCode is based on compoundName so this works.
+ break;
+ }
+ }
+ }
}
} \ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedAnnotationBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedAnnotationBinding.java
index 57952eaa7..b85916734 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedAnnotationBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedAnnotationBinding.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
*******************************************************************************/
@@ -19,7 +23,7 @@ UnresolvedAnnotationBinding(ReferenceBinding type, ElementValuePair[] pairs, Loo
this.env = env;
}
-public ReferenceBinding getAnnotationType() {
+public void resolve() { // in place resolution.
if (this.typeUnresolved) { // the type is resolved when requested
boolean wasToleratingMissingTypeProcessingAnnotations = this.env.mayTolerateMissingType;
this.env.mayTolerateMissingType = true; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=388042
@@ -31,13 +35,16 @@ public ReferenceBinding getAnnotationType() {
}
this.typeUnresolved = false;
}
+}
+public ReferenceBinding getAnnotationType() {
+ resolve();
return this.type;
}
public ElementValuePair[] getElementValuePairs() {
if (this.env != null) {
if (this.typeUnresolved) {
- getAnnotationType(); // resolve the annotation type
+ resolve();
}
// resolve method binding and value type (if unresolved) for each pair
for (int i = this.pairs.length; --i >= 0;) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
index ce6670099..4e3c02faf 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/UnresolvedReferenceBinding.java
@@ -27,7 +27,6 @@ public class UnresolvedReferenceBinding extends ReferenceBinding {
ReferenceBinding resolvedType;
TypeBinding[] wrappers;
UnresolvedReferenceBinding prototype;
-TypeBinding enclosingType;
//{ObjectTeams: make visible to subclass:
protected
@@ -48,11 +47,10 @@ public UnresolvedReferenceBinding(UnresolvedReferenceBinding prototype) {
this.prototype = prototype.prototype;
}
-public TypeBinding clone(TypeBinding outerType, TypeBinding[] someTypeArguments) {
- if (this.resolvedType != null)
+public TypeBinding clone(TypeBinding outerType) {
+ if (this.resolvedType != null || this.depth() > 0)
throw new IllegalStateException();
UnresolvedReferenceBinding copy = new UnresolvedReferenceBinding(this);
- copy.enclosingType = outerType;
this.addWrapper(copy, null);
return copy;
}
@@ -72,6 +70,9 @@ void addWrapper(TypeBinding wrapper, LookupEnvironment environment) {
this.wrappers[length] = wrapper;
}
}
+public boolean isUnresolvedType() {
+ return true;
+}
public String debugName() {
return toString();
}
@@ -84,6 +85,11 @@ public boolean hasTypeBit(int bit) {
// shouldn't happen since we are not called before analyseCode(), but play safe:
return false;
}
+
+public TypeBinding prototype() {
+ return this.prototype;
+}
+
//{ObjectTeams: changed to public (was default-vis)
public ReferenceBinding resolve(LookupEnvironment environment, boolean convertGenericToRawType) {
// SH}
@@ -130,8 +136,7 @@ void setResolvedType(ReferenceBinding targetType, LookupEnvironment environment)
public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding unannotatedType, LookupEnvironment environment) {
if (this.resolvedType != null) return;
- ReferenceBinding annotatedType = (ReferenceBinding) unannotatedType.clone(this.enclosingType != null ? this.enclosingType : unannotatedType.enclosingType(), null);
-
+ ReferenceBinding annotatedType = (ReferenceBinding) unannotatedType.clone(null);
this.resolvedType = annotatedType;
annotatedType.setTypeAnnotations(getTypeAnnotations(), environment.globalOptions.isAnnotationBasedNullAnalysisEnabled);
annotatedType.id = unannotatedType.id = this.id;
@@ -140,6 +145,7 @@ public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceB
this.wrappers[i].swapUnresolved(this, annotatedType, environment);
environment.updateCaches(this, annotatedType);
}
+
public String toString() {
if (this.hasTypeAnnotations())
return super.annotatedDebugName() + "(unresolved)"; //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
index 463130dd8..1d4846353 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java
@@ -16,6 +16,7 @@
* bug 349326 - [1.7] new warning for missing try-with-resources
* bug 359362 - FUP of bug 349326: Resource leak on non-Closeable resource
* bug 358903 - Filter practically unimportant resource leak warnings
+ * Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -57,12 +58,6 @@ public class WildcardBinding extends ReferenceBinding {
this.modifiers = ClassFileConstants.AccPublic | ExtraCompilerModifiers.AccGenericSignature; // treat wildcard as public
this.environment = environment;
initialize(genericType, bound, otherBounds);
-
-// if (!genericType.isGenericType() && !(genericType instanceof UnresolvedReferenceBinding)) {
-// RuntimeException e = new RuntimeException("WILDCARD with NON GENERIC");
-// e.printStackTrace();
-// throw e;
-// }
if (genericType instanceof UnresolvedReferenceBinding)
((UnresolvedReferenceBinding) genericType).addWrapper(this, environment);
if (bound instanceof UnresolvedReferenceBinding)
@@ -71,19 +66,6 @@ public class WildcardBinding extends ReferenceBinding {
this.typeBits = TypeIds.BitUninitialized;
}
- public WildcardBinding(WildcardBinding prototype) {
- super(prototype);
- this.genericType = prototype.genericType;
- this.rank = prototype.rank;
- this.bound = prototype.bound;
- this.otherBounds = prototype.otherBounds;
- this.genericSignature = prototype.genericSignature;
- this.boundKind = prototype.boundKind;
- this.superclass = prototype.superclass;
- this.superInterfaces = prototype.superInterfaces;
- this.typeVariable = prototype.typeVariable;
- this.environment = prototype.environment;
- }
//{ObjectTeams: role wrapping?
public TypeBinding maybeWrapQualifiedRoleType(Scope scope, Expression anchorExpr, ASTNode typedNode) {
@@ -451,8 +433,8 @@ public class WildcardBinding extends ReferenceBinding {
return erasure().constantPoolName();
}
- public TypeBinding clone(TypeBinding immaterial, TypeBinding[] irrelevant) {
- return new WildcardBinding(this);
+ public TypeBinding clone(TypeBinding immaterial) {
+ return new WildcardBinding(this.genericType, this.rank, this.bound, this.otherBounds, this.boundKind, this.environment);
}
public String annotatedDebugName() {
@@ -470,7 +452,7 @@ public class WildcardBinding extends ReferenceBinding {
return buffer.append(CharOperation.concat(TypeConstants.WILDCARD_NAME, TypeConstants.WILDCARD_EXTENDS, this.bound.annotatedDebugName().toCharArray())).toString();
buffer.append(this.bound.annotatedDebugName());
for (int i = 0, length = this.otherBounds.length; i < length; i++) {
- buffer.append('&').append(this.otherBounds[i].annotatedDebugName());
+ buffer.append(" & ").append(this.otherBounds[i].annotatedDebugName()); //$NON-NLS-1$
}
return buffer.toString();
default: // SUPER
@@ -633,7 +615,8 @@ public class WildcardBinding extends ReferenceBinding {
break;
case Wildcard.EXTENDS :
if (this.otherBounds == null) {
- buffer.append(TypeConstants.WILDCARD_NAME).append(TypeConstants.WILDCARD_EXTENDS).append(this.bound.readableName());
+ buffer.append(TypeConstants.WILDCARD_NAME).append(TypeConstants.WILDCARD_EXTENDS);
+ buffer.append(shortNames ? this.bound.shortReadableName(): this.bound.readableName());
} else {
buffer.append(this.bound.nullAnnotatedReadableName(options, shortNames));
for (int i = 0, length = this.otherBounds.length; i < length; i++) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
index 52c73a3bf..e158465f6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -29,6 +29,7 @@
* Andy Clement - Contributions for
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
* Bug 409250 - [1.8][compiler] Various loose ends in 308 code generation
+ * Bug 415821 - [1.8][compiler] CLASS_EXTENDS target type annotation missing for anonymous classes
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.parser;
@@ -50,9 +51,9 @@ import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
-import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
@@ -968,6 +969,7 @@ private int stateStackLengthStack[] = new int[0];
private boolean parsingJava8Plus;
protected int unstackedAct = ERROR_ACTION;
private boolean haltOnSyntaxError = false;
+private boolean tolerateDefaultClassMethods = false;
//{ObjectTeams: context info while parsing separate role files:
@@ -3126,7 +3128,7 @@ protected void consumeCatchFormalParameter() {
}
// SH}
if (extendedDimensions > 0) {
- type = type.copyDims(type.dimensions() + extendedDimensions);
+ type = augmentTypeWithAdditionalDimensions(type, extendedDimensions, null, false);
type.sourceEnd = this.endPosition;
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=391092
if (type instanceof UnionTypeReference) {
@@ -4230,6 +4232,7 @@ protected void consumeEnterAnonymousClassBody(boolean qualified) {
TypeDeclaration anonymousType = new TypeDeclaration(this.compilationUnit.compilationResult);
anonymousType.name = CharOperation.NO_CHAR;
anonymousType.bits |= (ASTNode.IsAnonymousType|ASTNode.IsLocalType);
+ anonymousType.bits |= (typeReference.bits & ASTNode.HasTypeAnnotations);
QualifiedAllocationExpression alloc = new QualifiedAllocationExpression(anonymousType);
markEnclosingMemberWithLocalType();
pushOnAstStack(anonymousType);
@@ -4302,9 +4305,9 @@ protected void consumeEnterVariable() {
char[] identifierName = this.identifierStack[this.identifierPtr];
long namePosition = this.identifierPositionStack[this.identifierPtr];
- int extendedDimension = this.intStack[this.intPtr--];
+ int extendedDimensions = this.intStack[this.intPtr--];
// pop any annotations on extended dimensions now, so they don't pollute the base dimensions.
- Annotation [][] annotationsOnExtendedDimensions = extendedDimension == 0 ? null : getAnnotationsOnDimensions(extendedDimension);
+ Annotation [][] annotationsOnExtendedDimensions = extendedDimensions == 0 ? null : getAnnotationsOnDimensions(extendedDimensions);
AbstractVariableDeclaration declaration;
// create the ast node
boolean isLocalDeclaration = this.nestedMethod[this.nestedType] != 0;
@@ -4322,7 +4325,6 @@ protected void consumeEnterVariable() {
this.identifierLengthPtr--;
TypeReference type;
int variableIndex = this.variablesCounter[this.nestedType];
- int typeDim = 0;
if (variableIndex == 0) {
// first variable of the declaration (FieldDeclaration or LocalDeclaration)
if (isLocalDeclaration) {
@@ -4338,14 +4340,14 @@ protected void consumeEnterVariable() {
0,
length);
}
- type = getTypeReference(typeDim = this.intStack[this.intPtr--]); // type dimension
+ type = getTypeReference(this.intStack[this.intPtr--]); // type dimension
if (declaration.declarationSourceStart == -1) {
// this is true if there is no modifiers for the local variable declaration
declaration.declarationSourceStart = type.sourceStart;
}
pushOnAstStack(type);
} else {
- type = getTypeReference(typeDim = this.intStack[this.intPtr--]); // type dimension
+ type = getTypeReference(this.intStack[this.intPtr--]); // type dimension
pushOnAstStack(type);
declaration.declarationSourceStart = this.intStack[this.intPtr--];
declaration.modifiers = this.intStack[this.intPtr--];
@@ -4366,7 +4368,6 @@ protected void consumeEnterVariable() {
this.javadoc = null;
} else {
type = (TypeReference) this.astStack[this.astPtr - variableIndex];
- typeDim = type.dimensions();
AbstractVariableDeclaration previousVariable =
(AbstractVariableDeclaration) this.astStack[this.astPtr];
declaration.declarationSourceStart = previousVariable.declarationSourceStart;
@@ -4378,19 +4379,9 @@ protected void consumeEnterVariable() {
}
}
- if (extendedDimension == 0) {
- declaration.type = type;
- declaration.bits |= (type.bits & ASTNode.HasTypeAnnotations);
- } else {
- int dimension = typeDim + extendedDimension;
- Annotation [][] annotationsOnAllDimensions = null;
- Annotation[][] annotationsOnDimensions = type.getAnnotationsOnDimensions();
- if (annotationsOnDimensions != null || annotationsOnExtendedDimensions != null) {
- annotationsOnAllDimensions = getMergedAnnotationsOnDimensions(typeDim, annotationsOnDimensions, extendedDimension, annotationsOnExtendedDimensions);
-// declaration.bits |= (type.bits & ASTNode.HasTypeAnnotations);
- }
- declaration.type = copyDims(type, dimension, annotationsOnAllDimensions);
- }
+ declaration.type = extendedDimensions == 0 ? type : augmentTypeWithAdditionalDimensions(type, extendedDimensions, annotationsOnExtendedDimensions, false);
+ declaration.bits |= (type.bits & ASTNode.HasTypeAnnotations);
+
this.variablesCounter[this.nestedType]++;
pushOnAstStack(declaration);
// recovery
@@ -4416,27 +4407,6 @@ protected void consumeEnterVariable() {
this.lastIgnoredToken = -1;
}
}
-protected Annotation[][] getMergedAnnotationsOnDimensions(int dims, Annotation[][] annotationsOnDimensions,
- int extendedDims, Annotation[][] annotationsOnExtendedDimensions) {
-
- if (annotationsOnDimensions == null && annotationsOnExtendedDimensions == null)
- return null;
-
- Annotation [][] mergedAnnotations = new Annotation[dims + extendedDims][];
-
- if (annotationsOnDimensions != null) {
- for (int i = 0; i < dims; i++) {
- mergedAnnotations[i] = annotationsOnDimensions[i];
- }
- }
- if (annotationsOnExtendedDimensions != null) {
- for (int i = dims, j = 0; i < dims + extendedDims; i++, j++) {
- mergedAnnotations[i] = annotationsOnExtendedDimensions[j];
- }
- }
-
- return mergedAnnotations;
-}
protected void consumeEnumBodyNoConstants() {
// nothing to do
// The 0 on the astLengthStack has been pushed by EnumBodyDeclarationsopt
@@ -5179,7 +5149,7 @@ protected void consumeFormalParameter(boolean isVarArgs) {
roleRef = getTypeReference(roleFirstDimensions);
int roleDimensions = roleFirstDimensions + extendedDimensions + (isVarArgs?1:0);
if (roleDimensions > roleFirstDimensions)
- roleRef = roleRef.copyDims(roleDimensions); // annotsOnDIms?
+ roleRef = roleRef.augmentTypeWithAdditionalDimensions(roleDimensions, null, false); // annotsOnDIms?
// done role side, the following balances the pushs from consumeBeginLiftingType():
this.genericsIdentifiersLengthPtr--;
this.genericsLengthPtr--;
@@ -5194,19 +5164,13 @@ protected void consumeFormalParameter(boolean isVarArgs) {
type = ltr;
}
// SH}
- final int typeDimensions = firstDimensions + extendedDimensions + (isVarArgs ? 1 : 0);
-
- if (typeDimensions != firstDimensions) {
- // jsr308 type annotations management
- Annotation [][] annotationsOnFirstDimensions = firstDimensions == 0 ? null : type.getAnnotationsOnDimensions();
- Annotation [][] annotationsOnAllDimensions = annotationsOnFirstDimensions;
- if (annotationsOnExtendedDimensions != null) {
- annotationsOnAllDimensions = getMergedAnnotationsOnDimensions(firstDimensions, annotationsOnFirstDimensions, extendedDimensions, annotationsOnExtendedDimensions);
- }
- if (varArgsAnnotations != null) {
- annotationsOnAllDimensions = getMergedAnnotationsOnDimensions(firstDimensions + extendedDimensions, annotationsOnAllDimensions, 1, new Annotation[][]{varArgsAnnotations});
+ if (isVarArgs || extendedDimensions != 0) {
+ if (isVarArgs) {
+ type = augmentTypeWithAdditionalDimensions(type, 1, varArgsAnnotations != null ? new Annotation[][] { varArgsAnnotations } : null, true);
+ }
+ if (extendedDimensions != 0) {
+ type = augmentTypeWithAdditionalDimensions(type, extendedDimensions, annotationsOnExtendedDimensions, false);
}
- type = copyDims(type, typeDimensions, annotationsOnAllDimensions);
type.sourceEnd = type.isParameterizedTypeReference() ? this.endStatementPosition : this.endPosition;
}
if (isVarArgs) {
@@ -5855,7 +5819,7 @@ protected void consumeMethodBody() {
// MethodBody ::= NestedMethod '{' BlockStatementsopt '}'
this.nestedMethod[this.nestedType] --;
}
-protected void consumeMethodDeclaration(boolean isNotAbstract) {
+protected void consumeMethodDeclaration(boolean isNotAbstract, boolean isDefaultMethod) {
// MethodDeclaration ::= MethodHeader MethodBody
// AbstractMethodDeclaration ::= MethodHeader ';'
@@ -5914,6 +5878,9 @@ protected void consumeMethodDeclaration(boolean isNotAbstract) {
// a trailing comment behind the end of the method
md.bodyEnd = this.endPosition;
md.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+ if (isDefaultMethod && !this.tolerateDefaultClassMethods) {
+ problemReporter().defaultModifierIllegallySpecified(md.bodyStart, this.endPosition);
+ }
}
protected void consumeMethodHeader() {
// MethodHeader ::= MethodHeaderName MethodHeaderParameters MethodHeaderExtendedDims ThrowsClauseopt
@@ -5983,21 +5950,13 @@ protected void consumeMethodHeaderExtendedDims() {
// MethodHeaderExtendedDims ::= Dimsopt
// now we update the returnType of the method
MethodDeclaration md = (MethodDeclaration) this.astStack[this.astPtr];
- int extendedDims = this.intStack[this.intPtr--];
+ int extendedDimensions = this.intStack[this.intPtr--];
if(md.isAnnotationMethod()) {
- ((AnnotationMethodDeclaration)md).extendedDimensions = extendedDims;
+ ((AnnotationMethodDeclaration)md).extendedDimensions = extendedDimensions;
}
- if (extendedDims != 0) {
- TypeReference returnType = md.returnType;
+ if (extendedDimensions != 0) {
md.sourceEnd = this.endPosition;
- int dims = returnType.dimensions() + extendedDims;
- Annotation [][] annotationsOnDimensions = returnType.getAnnotationsOnDimensions();
- Annotation [][] annotationsOnExtendedDimensions = getAnnotationsOnDimensions(extendedDims);
- Annotation [][] annotationsOnAllDimensions = null;
- if (annotationsOnDimensions != null || annotationsOnExtendedDimensions != null) {
- annotationsOnAllDimensions = getMergedAnnotationsOnDimensions(returnType.dimensions(), annotationsOnDimensions, extendedDims, annotationsOnExtendedDimensions);
- }
- md.returnType = copyDims(returnType, dims, annotationsOnAllDimensions);
+ md.returnType = augmentTypeWithAdditionalDimensions(md.returnType, extendedDimensions, getAnnotationsOnDimensions(extendedDimensions), false);
if (this.currentToken == TokenNameLBRACE){
md.bodyStart = this.endPosition + 1;
}
@@ -6654,6 +6613,7 @@ protected void consumeTypeAnnotation() {
Annotation annotation = this.typeAnnotationStack[this.typeAnnotationPtr];
problemReporter().invalidUsageOfTypeAnnotations(annotation);
}
+ this.dimensions = this.intStack[this.intPtr--]; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=417660
}
protected void consumeOneMoreTypeAnnotation() {
// TypeAnnotations ::= TypeAnnotations TypeAnnotation
@@ -7338,7 +7298,7 @@ private void rejectIllegalTypeAnnotations(TypeReference typeReference) {
problemReporter().misplacedTypeAnnotations(misplacedAnnotations[0], misplacedAnnotations[misplacedAnnotations.length - 1]);
}
}
- annotations = typeReference.getAnnotationsOnDimensions();
+ annotations = typeReference.getAnnotationsOnDimensions(true);
for (int i = 0, length = annotations == null ? 0 : annotations.length; i < length; i++) {
misplacedAnnotations = annotations[i];
if (misplacedAnnotations != null) {
@@ -7932,12 +7892,12 @@ protected void consumeRule(int act) {
case 230 : if (DEBUG) { System.out.println("MethodDeclaration ::= MethodHeader MethodBody"); } //$NON-NLS-1$
// set to true to consume a method with a body
- consumeMethodDeclaration(true);
+ consumeMethodDeclaration(true, false);
break;
case 231 : if (DEBUG) { System.out.println("AbstractMethodDeclaration ::= MethodHeader SEMICOLON"); } //$NON-NLS-1$
// set to false to consume a method without body
- consumeMethodDeclaration(false);
+ consumeMethodDeclaration(false, false);
break;
case 232 : if (DEBUG) { System.out.println("MethodHeader ::= MethodHeaderName FormalParameterListopt"); } //$NON-NLS-1$
@@ -11200,6 +11160,9 @@ protected void consumeToken(int type) {
this.lParenPos = this.scanner.startPosition;
break;
case TokenNameAT308:
+ pushOnIntStack(this.dimensions); // https://bugs.eclipse.org/bugs/show_bug.cgi?id=417660: Stack the dimensions, they get unstacked in consumeTypeAnnotation.
+ this.dimensions = 0;
+ //$FALL-THROUGH$
case TokenNameAT :
//{ObjectTeams: 3rd variant of '@':
case TokenNameATOT:
@@ -11296,44 +11259,6 @@ private boolean doingOrgObjectteamsInternalType() {
&& CharOperation.equals(this.compilationUnit.currentPackage.tokens, IOTConstants.ORG_OBJECTTEAMS);
}
// SH}
-protected void consumeTypeArgument() {
- pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));
-}
-protected void consumeTypeArgumentList() {
- concatGenericsLists();
-}
-protected void consumeTypeArgumentList1() {
- concatGenericsLists();
-}
-protected void consumeTypeArgumentList2() {
- concatGenericsLists();
-}
-protected void consumeTypeArgumentList3() {
- concatGenericsLists();
-}
-protected void consumeTypeArgumentReferenceType1() {
- concatGenericsLists();
- pushOnGenericsStack(getTypeReference(0));
- this.intPtr--; // pop '<' position.
-}
-protected void consumeTypeArgumentReferenceType2() {
- concatGenericsLists();
- pushOnGenericsStack(getTypeReference(0));
- this.intPtr--;
-}
-protected void consumeTypeArguments() {
- concatGenericsLists();
- this.intPtr--;
-
- if(!this.statementRecoveryActivated &&
- this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
- this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
- int length = this.genericsLengthStack[this.genericsLengthPtr];
- problemReporter().invalidUsageOfTypeArguments(
- (TypeReference)this.genericsStack[this.genericsPtr - length + 1],
- (TypeReference)this.genericsStack[this.genericsPtr]);
- }
-}
//{ObjectTeams: new syntax for dependent types.
protected void consumeTypeAnchor(boolean haveBase) {
// TentativeTypeAnchor ::= '@OT' UnannotatableName
@@ -11529,6 +11454,44 @@ protected void consumeBoundsOfAnchoredTypeParameter() {
parameter.bounds = new TypeReference[] { bound };
}
// SH}
+protected void consumeTypeArgument() {
+ pushOnGenericsStack(getTypeReference(this.intStack[this.intPtr--]));
+}
+protected void consumeTypeArgumentList() {
+ concatGenericsLists();
+}
+protected void consumeTypeArgumentList1() {
+ concatGenericsLists();
+}
+protected void consumeTypeArgumentList2() {
+ concatGenericsLists();
+}
+protected void consumeTypeArgumentList3() {
+ concatGenericsLists();
+}
+protected void consumeTypeArgumentReferenceType1() {
+ concatGenericsLists();
+ pushOnGenericsStack(getTypeReference(0));
+ this.intPtr--; // pop '<' position.
+}
+protected void consumeTypeArgumentReferenceType2() {
+ concatGenericsLists();
+ pushOnGenericsStack(getTypeReference(0));
+ this.intPtr--;
+}
+protected void consumeTypeArguments() {
+ concatGenericsLists();
+ this.intPtr--;
+
+ if(!this.statementRecoveryActivated &&
+ this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ int length = this.genericsLengthStack[this.genericsLengthPtr];
+ problemReporter().invalidUsageOfTypeArguments(
+ (TypeReference)this.genericsStack[this.genericsPtr - length + 1],
+ (TypeReference)this.genericsStack[this.genericsPtr]);
+ }
+}
protected void consumeTypeDeclarations() {
// TypeDeclarations ::= TypeDeclarations TypeDeclaration
concatNodeLists();
@@ -12006,12 +11969,8 @@ public MethodDeclaration convertToMethodDeclaration(ConstructorDeclaration c, Co
return m;
}
-protected TypeReference copyDims(TypeReference typeRef, int dim) {
- return typeRef.copyDims(dim);
-}
-
-protected TypeReference copyDims(TypeReference typeRef, int dim, Annotation[][]annotationsOnDimensions) {
- return typeRef.copyDims(dim, annotationsOnDimensions);
+protected TypeReference augmentTypeWithAdditionalDimensions(TypeReference typeReference, int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) {
+ return typeReference.augmentTypeWithAdditionalDimensions(additionalDimensions, additionalAnnotations, isVarargs);
}
protected FieldDeclaration createFieldDeclaration(char[] fieldDeclarationName, int sourceStart, int sourceEnd) {
@@ -14150,6 +14109,7 @@ public void parse(AbstractMethodMappingDeclaration mapping, CompilationUnitDecla
// SH}
public ASTNode[] parseClassBodyDeclarations(char[] source, int offset, int length, CompilationUnitDeclaration unit) {
boolean oldDiet = this.diet;
+ boolean oldTolerateDefaultClassMethods = this.tolerateDefaultClassMethods;
/* automaton initialization */
initialize();
goForClassBodyDeclarations();
@@ -14176,11 +14136,13 @@ public ASTNode[] parseClassBodyDeclarations(char[] source, int offset, int lengt
/* run automaton */
try {
this.diet = true;
+ this.tolerateDefaultClassMethods = this.parsingJava8Plus;
parse();
} catch (AbortCompilation ex) {
this.lastAct = ERROR_ACTION;
} finally {
this.diet = oldDiet;
+ this.tolerateDefaultClassMethods = oldTolerateDefaultClassMethods;
}
ASTNode[] result = null;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
index 3d2016181..8743de47f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
@@ -387,6 +387,7 @@ public class Scanner implements TerminalTokens {
private VanguardScanner vanguardScanner;
private VanguardParser vanguardParser;
private ConflictedParser activeParser = null;
+ private boolean consumingEllipsisAnnotations = false;
public static final int RoundBracket = 0;
public static final int SquareBracket = 1;
@@ -418,6 +419,7 @@ public Scanner(
this.tokenizeWhiteSpace = tokenizeWhiteSpace;
this.sourceLevel = sourceLevel;
this.lookBack[0] = this.lookBack[1] = this.nextToken = TokenNameNotAToken;
+ this.consumingEllipsisAnnotations = false;
this.complianceLevel = complianceLevel;
this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
if (taskTags != null) {
@@ -1358,6 +1360,8 @@ public int getNextToken() throws InvalidInputException {
}
if (token == TokenNameLPAREN || token == TokenNameLESS || token == TokenNameAT) {
token = disambiguatedToken(token);
+ } else if (token == TokenNameELLIPSIS) {
+ this.consumingEllipsisAnnotations = false;
}
this.lookBack[0] = this.lookBack[1];
this.lookBack[1] = token;
@@ -3368,6 +3372,7 @@ public void resetTo(int begin, int end) {
this.commentPtr = -1; // reset comment stack
this.foundTaskCount = 0;
this.lookBack[0] = this.lookBack[1] = this.nextToken = TokenNameNotAToken;
+ this.consumingEllipsisAnnotations = false;
//{ObjectTeams: lookahead on '->':
this._insideParameterMapping = false;
this._bindoutLookahead = null;
@@ -5357,7 +5362,9 @@ protected final boolean maybeAtReferenceExpression() { // Did the '<' we saw jus
}
return this.activeParser.atConflictScenario(TokenNameLESS);
}
-protected final boolean maybeAtEllipsisAnnotation() { // Did the '@' we saw just now herald a type annotation on a ... ? Presumed to be at type annotation already.
+private final boolean maybeAtEllipsisAnnotationsStart() { // Did the '@' we saw just now herald a type annotation on a ... ? Presumed to be at type annotation already.
+ if (this.consumingEllipsisAnnotations)
+ return false;
switch (this.lookBack[1]) {
case TokenNamenew:
case TokenNameCOMMA:
@@ -5411,8 +5418,9 @@ private int disambiguatedToken(int token) {
} else {
// orig:
token = TokenNameAT308;
- if (maybeAtEllipsisAnnotation()) {
+ if (maybeAtEllipsisAnnotationsStart()) {
if (parser.parse(Goal.VarargTypeAnnotationGoal) == VanguardParser.SUCCESS) {
+ this.consumingEllipsisAnnotations = true;
this.nextToken = TokenNameAT308;
return TokenNameAT308DOTDOTDOT;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index 608845bc5..dea319297 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -51,7 +51,9 @@
* bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
* bug 382721 - [1.8][compiler] Effectively final variables needs special treatment
* bug 384567 - [1.5][compiler] Compiler accepts illegal modifiers on package declaration
- *******************************************************************************/
+ * bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
+ * bug 412151 - [1.8][compiler] Check repeating annotation's collection type
+ ********************************************************************************/
package org.eclipse.jdt.internal.compiler.problem;
import java.io.CharConversionException;
@@ -143,6 +145,7 @@ import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
@@ -716,7 +719,7 @@ public static int getIrritant(int problemID) {
case IProblem.UnusedTypeParameter:
return CompilerOptions.UnusedTypeParameter;
- }
+}
return 0;
}
/**
@@ -1807,6 +1810,13 @@ public void defaultMethodOverridesObjectMethod(MethodBinding currentMethod) {
sourceStart, sourceEnd);
}
+public void defaultModifierIllegallySpecified(int sourceStart, int sourceEnd) {
+ this.handle(
+ IProblem.IllegalDefaultModifierSpecification,
+ NoArgument, NoArgument,
+ sourceStart, sourceEnd);
+}
+
public void deprecatedField(FieldBinding field, ASTNode location) {
int severity = computeSeverity(IProblem.UsingDeprecatedField);
if (severity == ProblemSeverities.Ignore) return;
@@ -1913,9 +1923,9 @@ public void multiCatchNotBelow17(ASTNode node) {
node.sourceStart,
node.sourceEnd);
}
-public void duplicateAnnotation(Annotation annotation) {
+public void duplicateAnnotation(Annotation annotation, long sourceLevel) {
this.handle(
- IProblem.DuplicateAnnotation,
+ sourceLevel >= ClassFileConstants.JDK1_8 ? IProblem.DuplicateAnnotationNotMarkedRepeatable : IProblem.DuplicateAnnotation,
new String[] {new String(annotation.resolvedType.readableName())},
new String[] {new String(annotation.resolvedType.shortReadableName())},
annotation.sourceStart,
@@ -7683,6 +7693,81 @@ public void referenceMustBeArrayTypeAt(TypeBinding arrayType, ArrayReference arr
arrayRef.sourceStart,
arrayRef.sourceEnd);
}
+public void repeatedAnnotationWithContainer(Annotation annotation, Annotation container) {
+ this.handle(
+ IProblem.RepeatedAnnotationWithContainerAnnotation,
+ new String[] {new String(annotation.resolvedType.readableName()), new String(container.resolvedType.readableName())},
+ new String[] {new String(annotation.resolvedType.shortReadableName()), new String(container.resolvedType.shortReadableName())},
+ annotation.sourceStart,
+ annotation.sourceEnd);
+}
+public void containingAnnotationMustHaveValue(ASTNode markerNode, ReferenceBinding containerAnnotationType) {
+ this.handle(
+ IProblem.ContainingAnnotationMustHaveValue,
+ new String[] {new String(containerAnnotationType.readableName())},
+ new String[] {new String(containerAnnotationType.shortReadableName())},
+ markerNode.sourceStart,
+ markerNode.sourceEnd);
+}
+public void containingAnnotationHasWrongValueType(ASTNode markerNode, ReferenceBinding containerAnnotationType, ReferenceBinding annotationType, TypeBinding returnType) {
+ this.handle(
+ IProblem.ContainingAnnotationHasWrongValueType,
+ new String[] {new String(containerAnnotationType.readableName()), new String(annotationType.readableName()), new String(returnType.readableName())},
+ new String[] {new String(containerAnnotationType.shortReadableName()), new String(annotationType.shortReadableName()), new String(returnType.shortReadableName())},
+ markerNode.sourceStart,
+ markerNode.sourceEnd);
+}
+public void containingAnnotationHasNonDefaultMembers(ASTNode markerNode, ReferenceBinding containerAnnotationType, char[] selector) {
+ this.handle(
+ IProblem.ContainingAnnotationHasNonDefaultMembers,
+ new String[] {new String(containerAnnotationType.readableName()), new String(selector)},
+ new String[] {new String(containerAnnotationType.shortReadableName()), new String(selector)},
+ markerNode.sourceStart,
+ markerNode.sourceEnd);
+}
+public void containingAnnotationHasShorterRetention(ASTNode markerNode, ReferenceBinding annotationType, String annotationRetention, ReferenceBinding containerAnnotationType, String containerRetention) {
+ this.handle(
+ IProblem.ContainingAnnotationHasShorterRetention,
+ new String[] {new String(annotationType.readableName()), annotationRetention, new String(containerAnnotationType.readableName()), containerRetention},
+ new String[] {new String(annotationType.shortReadableName()), annotationRetention, new String(containerAnnotationType.shortReadableName()), containerRetention},
+ markerNode.sourceStart,
+ markerNode.sourceEnd);
+}
+public void repeatableAnnotationHasTargets(ASTNode markerNode, ReferenceBinding annotationType, ReferenceBinding containerAnnotationType) {
+ this.handle(
+ IProblem.RepeatableAnnotationHasTargets,
+ new String[] {new String(annotationType.readableName()), new String(containerAnnotationType.readableName())},
+ new String[] {new String(annotationType.shortReadableName()), new String(containerAnnotationType.shortReadableName())},
+ markerNode.sourceStart,
+ markerNode.sourceEnd);
+}
+public void repeatableAnnotationTargetMismatch(ASTNode markerNode, ReferenceBinding annotationType, ReferenceBinding containerAnnotationType, String unmetTargets) {
+ this.handle(
+ IProblem.RepeatableAnnotationTargetMismatch,
+ new String[] {new String(annotationType.readableName()), new String(containerAnnotationType.readableName()), unmetTargets},
+ new String[] {new String(annotationType.shortReadableName()), new String(containerAnnotationType.shortReadableName()), unmetTargets},
+ markerNode.sourceStart,
+ markerNode.sourceEnd);
+}
+
+public void repeatableAnnotationIsDocumented(ASTNode markerNode, ReferenceBinding annotationType, ReferenceBinding containerAnnotationType) {
+ this.handle(
+ IProblem.RepeatableAnnotationIsDocumented,
+ new String[] {new String(annotationType.readableName()), new String(containerAnnotationType.readableName())},
+ new String[] {new String(annotationType.shortReadableName()), new String(containerAnnotationType.shortReadableName())},
+ markerNode.sourceStart,
+ markerNode.sourceEnd);
+}
+
+public void repeatableAnnotationIsInherited(ASTNode markerNode, ReferenceBinding annotationType, ReferenceBinding containerAnnotationType) {
+ this.handle(
+ IProblem.RepeatableAnnotationIsInherited,
+ new String[] {new String(annotationType.readableName()), new String(containerAnnotationType.readableName())},
+ new String[] {new String(annotationType.shortReadableName()), new String(containerAnnotationType.shortReadableName())},
+ markerNode.sourceStart,
+ markerNode.sourceEnd);
+}
+
public void reset() {
this.positionScanner = null;
}
@@ -9661,6 +9746,11 @@ public void nullityMismatch(Expression expression, TypeBinding providedType, Typ
nullityMismatchingTypeAnnotation(expression, providedType, requiredType, NullAnnotationMatching.NULL_ANNOTATIONS_UNCHECKED);
}
public void nullityMismatchIsNull(Expression expression, TypeBinding requiredType) {
+ if (requiredType instanceof CaptureBinding) {
+ CaptureBinding capture = (CaptureBinding) requiredType;
+ if (capture.wildcard != null)
+ requiredType = capture.wildcard;
+ }
int problemId = IProblem.RequiredNonNullButProvidedNull;
String[] arguments = new String[] {
annotatedTypeName(requiredType, this.options.nonNullAnnotationName)
@@ -14105,4 +14195,12 @@ public void illegalSuperCallBypassingOverride(InvocationSite location, MethodBin
location.sourceStart(),
location.sourceEnd());
}
+public void disallowedTargetForContainerAnnotation(Annotation annotation, TypeBinding containerAnnotationType) {
+ this.handle(
+ IProblem.DisallowedTargetForContainerAnnotation,
+ new String[] {new String(annotation.resolvedType.readableName()), new String(containerAnnotationType.readableName())},
+ new String[] {new String(annotation.resolvedType.shortReadableName()), new String(containerAnnotationType.shortReadableName())},
+ annotation.sourceStart,
+ annotation.sourceEnd);
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index c297bb949..fb4a81f27 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -41,6 +41,8 @@
# Jesper S Moller <jesper@selskabet.org> - Contributions for
# bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
# bug 384567 - [1.5][compiler] Compiler accepts illegal modifiers on package declaration
+# Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
+# Bug 412151 - [1.8][compiler] Check repeating annotation's collection type
###############################################################################
0 = {0}
1 = super cannot be used in java.lang.Object
@@ -588,7 +590,7 @@
605 = Invalid type {0} for the annotation attribute {2}.{1}; only primitive type, String, Class, annotation, enumeration are permitted or 1-dimensional arrays thereof
606 = Cycle detected: the annotation type {0} cannot contain attributes of the annotation type itself
607 = Cycle detected: a cycle exists between annotation attributes of {0} and {1}
-608 = Duplicate annotation @{0}
+608 = Duplicate annotation @{0}. Repeated annotations are allowed only at source level 1.8 or above
609 = The annotation @{0} must define the attribute {1}
610 = Duplicate attribute {0} in annotation @{1}
611 = The attribute {0} is undefined for the annotation type {1}
@@ -745,6 +747,18 @@
895 = The target type of this expression is not a functional interface: more than one of the intersecting interfaces are functional
896 = Static methods are allowed in interfaces only at source level 1.8 or above
+897 = Duplicate annotation of non-repeatable type @{0}. Only annotation types marked @Repeatable can be used multiple times at one target.
+898 = The repeatable annotation @{0} is disallowed for this location since its container annotation @{1} is disallowed at this location
+899 = The repeatable annotation @{0} may not be repeated where its container annotation @{1} is also used directly
+902 = The value method in the containing annotation @{0} must be of type {1}[] but is {2}
+903 = The containing annotation @{0} must declare a member value()
+904 = The containing annotation @{0} must declare a default value for the annotation attribute ''{1}''
+905 = Retention ''{1}'' of @{0} is longer than the retention of the containing annotation @{2}, which is ''{3}''
+906 = The repeatable annotation @{0} has a @Target annotation, @{1} does not
+907 = The containing annotation @{1} is allowed at targets where the repeatable annotation @{0} is not: {2}
+908 = The repeatable annotation @{0} is marked @Documented, but the containing annotation @{1} is not
+909 = The repeatable annotation @{0} is marked @Inherited, but the containing annotation @{1} is not
+
### NULL ANNOTATIONS
910 = Null type mismatch: required ''{0}'' but the provided value is null
911 = Null type mismatch: required ''{0}'' but the provided value is inferred as @{1}
@@ -811,6 +825,7 @@
1055 = Illegal reference to super method {0} from type {1}, cannot bypass the more specific override from type {2}
1056 = Illegal combination of modifiers for the interface method {0}; only one of abstract, default, or static permitted
1057 = strictfp is not permitted for abstract interface method {0}
+1058 = Default methods are allowed only in interfaces with source level 1.8 or greater.
### ELABORATIONS
## Access restrictions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfType.java
index 7931e510c..1e8e9ba95 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/HashtableOfType.java
@@ -60,6 +60,31 @@ public ReferenceBinding get(char[] key) {
}
return null;
}
+// Returns old value.
+public ReferenceBinding getput(char[] key, ReferenceBinding value) {
+ ReferenceBinding retVal = null;
+ int length = this.keyTable.length,
+ index = CharOperation.hashCode(key) % length;
+ int keyLength = key.length;
+ char[] currentKey;
+ while ((currentKey = this.keyTable[index]) != null) {
+ if (currentKey.length == keyLength && CharOperation.equals(currentKey, key)) {
+ retVal = this.valueTable[index];
+ this.valueTable[index] = value;
+ return retVal;
+ }
+ if (++index == length) {
+ index = 0;
+ }
+ }
+ this.keyTable[index] = key;
+ this.valueTable[index] = value;
+
+ // assumes the threshold is never equal to the size of the table
+ if (++this.elementSize > this.threshold)
+ rehash();
+ return retVal;
+}
public ReferenceBinding put(char[] key, ReferenceBinding value) {
int length = this.keyTable.length,
index = CharOperation.hashCode(key) % length;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/LiftingTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/LiftingTypeReference.java
index 22be86314..c5bb21046 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/LiftingTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/LiftingTypeReference.java
@@ -103,8 +103,9 @@ public class LiftingTypeReference extends TypeReference {
}
@Override
- public TypeReference copyDims(int dim, Annotation[][] annotationsOnDimensions) {
- this.baseReference = this.baseReference.copyDims(dim, annotationsOnDimensions);
+ public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs)
+ {
+ this.baseReference = this.baseReference.augmentTypeWithAdditionalDimensions(additionalDimensions, additionalAnnotations, isVarargs);
// FIXME check consistency
return this;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/TypeAnchorReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/TypeAnchorReference.java
index 8d32fa035..5565389e6 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/TypeAnchorReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/ast/TypeAnchorReference.java
@@ -104,12 +104,7 @@ public class TypeAnchorReference extends TypeReference implements InvocationSite
}
@Override
- public TypeReference copyDims(int dim) {
- throw new InternalCompilerError("Method not applicable");
- }
-
- @Override
- public TypeReference copyDims(int dim, Annotation[][] annotationsOnDimensions) {
+ public TypeReference augmentTypeWithAdditionalDimensions(int additionalDimensions, Annotation[][] additionalAnnotations, boolean isVarargs) {
throw new InternalCompilerError("Method not applicable");
}
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 276a9b7a3..7ed5c30b2 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
@@ -1004,6 +1004,14 @@ public final class AST {
}
/**
+ * A local method to workaround calling deprecated method in array type.
+ * @deprecated
+ */
+ private void setArrayComponentType(ArrayType arrayType, Type type) {
+ arrayType.setComponentType(type);
+ }
+
+ /**
* Creates and returns a new unparented annotation type declaration
* node for an unspecified, but legal, name; no modifiers; no javadoc;
* and an empty list of member declarations.
@@ -1148,19 +1156,31 @@ public final class AST {
/**
* Creates and returns a new unparented array type node with the given
- * component type, which may be another array type.
+ * component type, which may be another array type for levels less than JLS8.
+ * For JLS8 and above this type has to be an annotatable type.
*
- * @param componentType the component type (possibly another array type)
+ * @param type the component type (possibly another array type) for level less than JLS8,
+ * a <code>AnnotatableType</code> for JLS8 and above
* @return a new unparented array type node
* @exception IllegalArgumentException if:
* <ul>
* <li>the node belongs to a different AST</li>
* <li>the node already has a parent</li>
+ * <li> level is greater than or equal to JLS8 and type not an array type</li>
* </ul>
*/
- public ArrayType newArrayType(Type componentType) {
- ArrayType result = new ArrayType(this);
- result.setComponentType(componentType);
+ public ArrayType newArrayType(Type type) {
+ ArrayType result;
+ if (this.apiLevel < AST.JLS8) {
+ result = new ArrayType(this);
+ setArrayComponentType(result, type);
+ return result;
+ }
+ if (type.isArrayType()) {
+ throw new IllegalArgumentException();
+ }
+ result = new ArrayType(this);
+ result.setElementType(type);
return result;
}
@@ -1172,7 +1192,7 @@ public final class AST {
* element type of the result will not be the same as what was passed in.
* </p>
*
- * @param elementType the element type (can be an array type)
+ * @param elementType the element type (can be an array type for JLS8. For level JLS8 and above this should be an <code>AnnotatableType</code>)
* @param dimensions the number of dimensions, a positive number
* @return a new unparented array type node
* @exception IllegalArgumentException if:
@@ -1182,6 +1202,7 @@ public final class AST {
* <li>the element type is null</li>
* <li>the number of dimensions is lower than 1</li>
* <li>the number of dimensions is greater than 1000</li>
+ * <li>for levels from JLS8 and later, if the element type is not an array type </li>
* </ul>
*/
public ArrayType newArrayType(Type elementType, int dimensions) {
@@ -1192,10 +1213,24 @@ public final class AST {
// we would blow our stacks anyway with a 1000-D array
throw new IllegalArgumentException();
}
- ArrayType result = new ArrayType(this);
- result.setComponentType(elementType);
- for (int i = 2; i <= dimensions; i++) {
- result = newArrayType(result);
+ ArrayType result;
+ if (this.apiLevel < AST.JLS8) {
+ result = new ArrayType(this);
+ setArrayComponentType(result, elementType);
+ for (int i = 2; i <= dimensions; i++) {
+ result = newArrayType(result);
+ }
+ return result;
+ }
+ //level >= JLS8
+ if (elementType.isArrayType()) {
+ throw new IllegalArgumentException();
+ }
+ result = new ArrayType(this);
+ result.setElementType(elementType);
+ // index starting from 1 since there is a dimension already available by default.
+ for (int i = 1; i < dimensions; ++i) {
+ result.dimensions().add(new ExtraDimension(this));
}
return result;
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 dd7b2b054..5cc6cdbd9 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
@@ -460,6 +460,13 @@ class ASTConverter {
}
}
}
+
+ private void checkAndSetMalformed(ASTNode spannedNode, ASTNode spanningNode) {
+ if ((spannedNode.getFlags() & ASTNode.MALFORMED) != 0) {
+ spanningNode.setFlags(spanningNode.getFlags() | ASTNode.MALFORMED);
+ }
+ }
+
/**
* Internal access method to SingleVariableDeclaration#setExtraDimensions() for avoiding deprecated warnings
*
@@ -605,15 +612,27 @@ class ASTConverter {
protected void completeRecord(ArrayType arrayType, org.eclipse.jdt.internal.compiler.ast.ASTNode astNode) {
ArrayType array = arrayType;
+ this.recordNodes(arrayType, astNode);
+ if (this.ast.apiLevel() >= AST.JLS8) {
+ this.recordNodes(arrayType.getElementType(), astNode);
+ return;
+ }
int dimensions = array.getDimensions();
for (int i = 0; i < dimensions; i++) {
- Type componentType = array.getComponentType();
+ Type componentType = componentType(array);
this.recordNodes(componentType, astNode);
if (componentType.isArrayType()) {
array = (ArrayType) componentType;
}
}
}
+
+ /**
+ * @deprecated
+ */
+ private Type componentType(ArrayType array) {
+ return array.getComponentType();
+ }
public ASTNode convert(boolean isInterface, org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration methodDeclaration) {
checkCanceled();
@@ -1081,12 +1100,18 @@ class ASTConverter {
if (isVarArgs) {
setTypeForSingleVariableDeclaration(variableDecl, type, extraDimensions + 1);
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=391898
- if (type.isAnnotatable()) {
- AnnotatableType annotatableType = (AnnotatableType) type;
- if (this.ast.apiLevel() >= AST.JLS8 && !annotatableType.annotations().isEmpty()) {
- Iterator annotations = annotatableType.annotations().iterator();
- while (annotations.hasNext()) {
- Annotation annotation = (Annotation) annotations.next();
+ if (this.ast.apiLevel() >= AST.JLS8) {
+ List annotations = null;
+ if (type.isAnnotatable()) {
+ annotations = ((AnnotatableType) type).annotations();
+ } else if (type.isArrayType()) {
+ ArrayType arrayType = (ArrayType) type;
+ annotations = arrayType.dimensions().isEmpty() ? null : ((arrayType.getDimensionAt(0)).annotations());
+ }
+ if (annotations != null) {
+ Iterator iter = annotations.iterator();
+ while (iter.hasNext()) {
+ Annotation annotation = (Annotation) iter.next();
annotation.setParent(null, null);
variableDecl.varargsAnnotations().add(annotation);
}
@@ -1153,27 +1178,19 @@ class ASTConverter {
ArrayType arrayType = null;
if (type.isArrayType()) {
arrayType = (ArrayType) type;
- } else {
- arrayType = this.ast.newArrayType(type, dimensionsLength);
- if (this.resolveBindings) {
- completeRecord(arrayType, expression);
- }
- int start = type.getStartPosition();
- int end = type.getStartPosition() + type.getLength();
- int previousSearchStart = end - 1;
- ArrayType componentType = (ArrayType) type.getParent();
- for (int i = 0; i < dimensionsLength; i++) {
- previousSearchStart = retrieveRightBracketPosition(previousSearchStart + 1, this.compilationUnitSourceLength);
- componentType.setSourceRange(start, previousSearchStart - start + 1);
- componentType = (ArrayType) componentType.getParent();
+ if (expression.annotationsOnDimensions != null) {
+ if (this.ast.apiLevel() < AST.JLS8) {
+ arrayType.setFlags(arrayType.getFlags() | ASTNode.MALFORMED);
+ } else {
+ setTypeAnnotationsAndSourceRangeOnArray(arrayType, expression.annotationsOnDimensions);
+ }
}
- }
- if (expression.annotationsOnDimensions != null) {
- annotateType(arrayType, expression.annotationsOnDimensions);
+ } else {
+ arrayType = convertToArray(type, type.getStartPosition(), -1, dimensionsLength, expression.annotationsOnDimensions);
}
arrayCreation.setType(arrayType);
if (this.resolveBindings) {
- recordNodes(arrayType, expression);
+ completeRecord(arrayType, expression);
}
if (expression.initializer != null) {
arrayCreation.setInitializer(convert(expression.initializer));
@@ -3473,6 +3490,30 @@ class ASTConverter {
return packageDeclaration;
}
+ private ArrayType convertToArray(Type elementType, int sourceStart, int length, int dimensions, org.eclipse.jdt.internal.compiler.ast.Annotation[][] annotationsOnDimensions) {
+ ArrayType arrayType = this.ast.newArrayType(elementType, dimensions);
+ if (length > 0) arrayType.setSourceRange(sourceStart, length);
+ if (this.ast.apiLevel() < AST.JLS8) {
+ if (annotationsOnDimensions != null) {
+ arrayType.setFlags(arrayType.getFlags() | ASTNode.MALFORMED);
+ }
+ ArrayType subarrayType = arrayType;
+ int index = dimensions - 1;
+ int arrayEnd = retrieveProperRightBracketPosition(dimensions, sourceStart);
+ while (index > 0) {
+ subarrayType = (ArrayType) componentType(subarrayType);
+ int end = retrieveProperRightBracketPosition(index, sourceStart);
+ subarrayType.setSourceRange(sourceStart, end - sourceStart + 1);
+ index--;
+ }
+ if (length <= 0) arrayType.setSourceRange(sourceStart, arrayEnd - sourceStart + 1);
+ return arrayType;
+ }
+
+ setTypeAnnotationsAndSourceRangeOnArray(arrayType, annotationsOnDimensions);
+ return arrayType;
+ }
+
private EnumDeclaration convertToEnumDeclaration(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration typeDeclaration) {
checkCanceled();
// enum declaration cannot be built if the source is not >= 1.5, since enum is then seen as an identifier
@@ -3693,7 +3734,7 @@ class ASTConverter {
protected void setExtraAnnotatedDimensions(int start, int end, TypeReference type, final List extraAnnotatedDimensions, int extraDimension) {
if (extraDimension > 0) {
- org.eclipse.jdt.internal.compiler.ast.Annotation[][] annotationsOnDims = type.getAnnotationsOnDimensions();
+ org.eclipse.jdt.internal.compiler.ast.Annotation[][] annotationsOnDims = type.getAnnotationsOnDimensions(true);
int length = (annotationsOnDims == null) ? 0 : annotationsOnDims.length;
for (int i = (length - extraDimension); i < length; i++) {
ExtraDimension dim = convertToExtraDimensions(start, end, (annotationsOnDims == null) ? null : annotationsOnDims[i]);
@@ -3703,6 +3744,35 @@ class ASTConverter {
}
}
+ private void setTypeAnnotationsOnDimension(ExtraDimension currentDimension, org.eclipse.jdt.internal.compiler.ast.Annotation[][] annotationsOnDimensions, int dimension) {
+ if (annotationsOnDimensions == null) return;
+ org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations = annotationsOnDimensions[dimension];
+ if (annotations != null) {
+ for (int j = 0, length = annotations.length; j < length; j++) {
+ Annotation annotation = convert(annotations[j]);
+ currentDimension.annotations().add(annotation);
+ }
+ }
+ }
+
+ private void setTypeAnnotationsAndSourceRangeOnArray(ArrayType arrayType, org.eclipse.jdt.internal.compiler.ast.Annotation[][] annotationsOnDimensions) {
+ List dimensions = arrayType.dimensions();
+ Type elementType = arrayType.getElementType();
+ int start = elementType.getStartPosition();
+ int endElement = start + elementType.getLength();
+ int length = arrayType.getLength();
+ int end = (length <= 0) ? retrieveProperRightBracketPosition(dimensions.size(), endElement) : start + length - 1;
+ arrayType.setSourceRange(start, end - start + 1);
+
+ start = endElement;
+ for (int i = 0; i < dimensions.size(); i++) {
+ ExtraDimension currentDimension = (ExtraDimension) dimensions.get(i);
+ setTypeAnnotationsOnDimension(currentDimension, annotationsOnDimensions, i);
+ retrieveDimensionAndSetPositions(start, end, currentDimension);
+ start = currentDimension.getStartPosition() + currentDimension.getLength();
+ }
+ }
+
protected VariableDeclarationStatement convertToVariableDeclarationStatement(org.eclipse.jdt.internal.compiler.ast.LocalDeclaration localDeclaration) {
final VariableDeclarationFragment variableDeclarationFragment = convertToVariableDeclarationFragment(localDeclaration);
final VariableDeclarationStatement variableDeclarationStatement = new VariableDeclarationStatement(this.ast);
@@ -3727,6 +3797,9 @@ class ASTConverter {
type.setFlags(type.getFlags() | ASTNode.MALFORMED);
break;
default:
+ if (annotations == null) break;
+ int start = type.getStartPosition();
+ int length = type.getLength();
int annotationsLength = annotations.length;
for (int i = 0; i < annotationsLength; i++) {
org.eclipse.jdt.internal.compiler.ast.Annotation typeAnnotation = annotations[i];
@@ -3735,20 +3808,14 @@ class ASTConverter {
type.annotations().add(annotation);
}
}
+ int annotationsStart;
+ if (annotations[0] != null && (annotationsStart = annotations[0].sourceStart) < start && annotationsStart > 0) {
+ length += start - annotationsStart;
+ start = annotationsStart;
+ }
+ type.setSourceRange(start, length);
}
}
- private void annotateType(Type type, org.eclipse.jdt.internal.compiler.ast.Annotation[][] annotations) {
- int level = annotations.length - 1;
- while(type.isArrayType()) {
- ArrayType arrayType = (ArrayType) type;
- org.eclipse.jdt.internal.compiler.ast.Annotation[] typeAnnotations = annotations[level--];
- if (typeAnnotations != null) {
- annotateType(arrayType, typeAnnotations);
- }
- type = arrayType.getComponentType();
- }
- }
-
private void annotateTypeParameter(TypeParameter typeParameter, org.eclipse.jdt.internal.compiler.ast.Annotation[] annotations) {
switch(this.ast.apiLevel) {
case AST.JLS2_INTERNAL :
@@ -3916,23 +3983,7 @@ class ASTConverter {
}
}
if (dimensions != 0) {
- org.eclipse.jdt.internal.compiler.ast.Annotation[][] annotationsOnDimensions = typeReference.getAnnotationsOnDimensions();
- type = this.ast.newArrayType(type, dimensions);
- type.setSourceRange(sourceStart, length);
- ArrayType subarrayType = (ArrayType) type;
- int index = dimensions - 1;
- while (index > 0) {
- if (annotationsOnDimensions != null && (annotations = annotationsOnDimensions[index]) != null) {
- annotateType(subarrayType, annotations);
- }
- subarrayType = (ArrayType) subarrayType.getComponentType();
- int end = retrieveProperRightBracketPosition(index, sourceStart);
- subarrayType.setSourceRange(sourceStart, end - sourceStart + 1);
- index--;
- }
- if (annotationsOnDimensions != null && (annotations = annotationsOnDimensions[0]) != null) {
- annotateType(subarrayType, annotations);
- }
+ type = convertToArray(type, sourceStart, length, dimensions, typeReference.getAnnotationsOnDimensions(true));
if (this.resolveBindings) {
// store keys for inner types
completeRecord((ArrayType) type, typeReference);
@@ -4200,31 +4251,10 @@ class ASTConverter {
length = typeReference.sourceEnd - sourceStart + 1;
if (dimensions != 0) {
- org.eclipse.jdt.internal.compiler.ast.Annotation[][] annotationsOnDimensions = typeReference.getAnnotationsOnDimensions();
- type = this.ast.newArrayType(type, dimensions);
+ type = convertToArray(type, sourceStart, -1, dimensions, typeReference.getAnnotationsOnDimensions(true));
if (this.resolveBindings) {
completeRecord((ArrayType) type, typeReference);
}
- int end = retrieveEndOfDimensionsPosition(sourceStart+length, this.compilationUnitSourceLength);
- if (end != -1) {
- type.setSourceRange(sourceStart, end - sourceStart + 1);
- } else {
- type.setSourceRange(sourceStart, length);
- }
- ArrayType subarrayType = (ArrayType) type;
- int index = dimensions - 1;
- while (index > 0) {
- if (annotationsOnDimensions != null && (annotations = annotationsOnDimensions[index]) != null) {
- annotateType(subarrayType, annotations);
- }
- subarrayType = (ArrayType) subarrayType.getComponentType();
- end = retrieveProperRightBracketPosition(index, sourceStart);
- subarrayType.setSourceRange(sourceStart, end - sourceStart + 1);
- index--;
- }
- if (annotationsOnDimensions != null && (annotations = annotationsOnDimensions[0]) != null) {
- annotateType(subarrayType, annotations);
- }
}
}
if (this.resolveBindings) {
@@ -4284,16 +4314,11 @@ class ASTConverter {
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;
+ annotatableType.setSourceRange(start, length);
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);
}
@@ -4991,38 +5016,6 @@ class ASTConverter {
}
/**
- * This method is used to retrieve the ending position for a type declaration when the dimension is right after the type
- * name.
- * For example:
- * int[] i; => return 5, but int i[] => return -1;
- * @return int the dimension found
- */
- protected int retrieveEndOfDimensionsPosition(int start, int end) {
- this.scanner.resetTo(start, end);
- int foundPosition = -1;
- try {
- int token;
- while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
- switch(token) {
- case TerminalTokens.TokenNameLBRACKET:
- case TerminalTokens.TokenNameCOMMENT_BLOCK:
- case TerminalTokens.TokenNameCOMMENT_JAVADOC:
- case TerminalTokens.TokenNameCOMMENT_LINE:
- break;
- case TerminalTokens.TokenNameRBRACKET://166
- foundPosition = this.scanner.currentPosition - 1;
- break;
- default:
- return foundPosition;
- }
- }
- } catch(InvalidInputException e) {
- // ignore
- }
- return foundPosition;
- }
-
- /**
* This method is used to retrieve the start and end position of a name or primitive type token.
*
* @return int[] a single dimensional array, with two elements, for the start and end positions of the name respectively
@@ -5032,8 +5025,15 @@ class ASTConverter {
boolean isAnnotation = false;
try {
int token;
+ int count = 0;
while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
switch(token) {
+ case TerminalTokens.TokenNameLPAREN:
+ ++count;
+ break;
+ case TerminalTokens.TokenNameRPAREN:
+ --count;
+ break;
case TerminalTokens.TokenNameAT:
isAnnotation = true;
break;
@@ -5051,6 +5051,7 @@ class ASTConverter {
case TerminalTokens.TokenNamelong:
case TerminalTokens.TokenNameshort:
case TerminalTokens.TokenNameboolean:
+ if (count > 0) break;
return new int[]{this.scanner.startPosition, this.scanner.currentPosition - 1};
}
}
@@ -5100,9 +5101,17 @@ class ASTConverter {
this.scanner.resetTo(start, end);
int dimensions = 0;
try {
- int token;
- boolean isAnnotation = false;
+ int token, lParenCount = 0;
+ boolean isAnnotation = false, foundAnnotation = false;
while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
+ if (foundAnnotation) {
+ if (token == TerminalTokens.TokenNameLPAREN) ++lParenCount;
+ else if (token == TerminalTokens.TokenNameRPAREN) {
+ --lParenCount;
+ continue;
+ }
+ if (lParenCount > 0) continue;
+ }
switch(token) {
case TerminalTokens.TokenNameLBRACKET:
case TerminalTokens.TokenNameCOMMENT_BLOCK:
@@ -5112,6 +5121,7 @@ class ASTConverter {
break;
case TerminalTokens.TokenNameAT:
isAnnotation = true;
+ foundAnnotation = true; /* check for params */
break;
case TerminalTokens.TokenNameIdentifier:
if (!isAnnotation) {
@@ -5136,22 +5146,36 @@ class ASTConverter {
protected void retrieveDimensionAndSetPositions(int start, int end, ExtraDimension dim) {
this.scanner.resetTo(start, end);
int token;
+ int count = 0, lParenCount = 0;
boolean startSet = false;
try {
while((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
- switch(token) {
- case TerminalTokens.TokenNameWHITESPACE:
- break;
- case TerminalTokens.TokenNameRBRACKET:
- int endDim = this.scanner.currentPosition - 1;
- dim.setSourceRange(start, endDim - start + 1);
- return;
- default:
- if (!startSet) {
- start = this.scanner.startPosition;
- startSet = true;
- }
- break;
+ if (token != TerminalTokens.TokenNameWHITESPACE) {
+ if (!startSet) {
+ start = this.scanner.startPosition;
+ startSet = true;
+ }
+ switch(token) {
+ case TerminalTokens.TokenNameRBRACKET:
+ if (lParenCount > 0) break;
+ --count;
+ if (count > 0) break;
+ int endDim = this.scanner.currentPosition - 1;
+ dim.setSourceRange(start, endDim - start + 1);
+ return;
+ case TerminalTokens.TokenNameLBRACKET:
+ if (lParenCount > 0) break;
+ count++;
+ break;
+ case TerminalTokens.TokenNameLPAREN:
+ lParenCount++;
+ break;
+ case TerminalTokens.TokenNameRPAREN:
+ --lParenCount;
+ break;
+ default:
+ break;
+ }
}
}
} catch(InvalidInputException e) {
@@ -5232,10 +5256,22 @@ class ASTConverter {
int balance = 0;
int pos = initializerEnd > nameEnd ? initializerEnd - 1 : nameEnd;
try {
- int token;
+ int token, lParenCount = 0;
+ boolean hasAnnotations = false;
while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
hasTokens = true;
+ if (hasAnnotations) {
+ if (token == TerminalTokens.TokenNameLPAREN) ++lParenCount;
+ else if (token == TerminalTokens.TokenNameRPAREN) {
+ --lParenCount;
+ continue;
+ }
+ if (lParenCount > 0) continue;
+ }
switch(token) {
+ case TerminalTokens.TokenNameAT:
+ hasAnnotations = true;
+ break;
case TerminalTokens.TokenNameLBRACE :
case TerminalTokens.TokenNameLBRACKET :
balance++;
@@ -5265,10 +5301,22 @@ class ASTConverter {
protected int retrieveProperRightBracketPosition(int bracketNumber, int start) {
this.scanner.resetTo(start, this.compilationUnitSourceLength);
try {
- int token, count = 0;
+ int token, count = 0, lParentCount = 0, balance = 0;
while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
switch(token) {
+ case TerminalTokens.TokenNameLPAREN:
+ ++lParentCount;
+ break;
+ case TerminalTokens.TokenNameRPAREN:
+ --lParentCount;
+ break;
+ case TerminalTokens.TokenNameLBRACKET:
+ ++balance;
+ break;
case TerminalTokens.TokenNameRBRACKET:
+ --balance;
+ if (lParentCount > 0) break;
+ if (balance > 0) break;
count++;
if (count == bracketNumber) {
return this.scanner.currentPosition - 1;
@@ -5324,32 +5372,6 @@ class ASTConverter {
}
/**
- * This method is used to retrieve the position of the right bracket.
- * @return int the dimension found, -1 if none
- */
- protected int retrieveRightBracketPosition(int start, int end) {
- this.scanner.resetTo(start, end);
- try {
- int token;
- int balance = 0;
- while ((token = this.scanner.getNextToken()) != TerminalTokens.TokenNameEOF) {
- switch(token) {
- case TerminalTokens.TokenNameLBRACKET :
- balance++;
- break;
- case TerminalTokens.TokenNameRBRACKET :
- balance--;
- if (balance == 0) return this.scanner.currentPosition - 1;
- break;
- }
- }
- } catch(InvalidInputException e) {
- // ignore
- }
- return -1;
- }
-
- /**
* This method is used to retrieve the start position of the block.
* @return int the dimension found, -1 if none
*/
@@ -6068,26 +6090,16 @@ class ASTConverter {
this.ast.getBindingResolver().updateKey(type, elementType);
fieldDeclaration.setType(elementType);
} else {
- int start = type.getStartPosition();
- ArrayType subarrayType = arrayType;
- int index = extraDimension;
- while (index > 0) {
- subarrayType = (ArrayType) subarrayType.getComponentType();
- index--;
- }
- int end = retrieveProperRightBracketPosition(remainingDimensions, start);
- subarrayType.setSourceRange(start, end - start + 1);
- // cut the child loose from its parent (without creating garbage)
- subarrayType.setParent(null, null);
+ ArrayType subarrayType = extractSubArrayType(arrayType, remainingDimensions, extraDimension);
fieldDeclaration.setType(subarrayType);
- updateInnerPositions(subarrayType, remainingDimensions);
this.ast.getBindingResolver().updateKey(type, subarrayType);
}
+ checkAndSetMalformed(type, fieldDeclaration);
} else {
fieldDeclaration.setType(type);
}
} else {
- if (type.isArrayType()) {
+ if (type.isArrayType() && (this.ast.apiLevel() < AST.JLS8)) {
// update positions of the component types of the array type
int dimensions = ((ArrayType) type).getDimensions();
updateInnerPositions(type, dimensions);
@@ -6096,6 +6108,35 @@ class ASTConverter {
}
}
+ /** extracts the subArrayType for a given declaration for AST levels less
+ * @param arrayType parent type
+ * @param remainingDimensions
+ * @param extraDimensions
+ * @return an ArrayType
+ */
+ private ArrayType extractSubArrayType(ArrayType arrayType, int remainingDimensions, int extraDimensions) {
+ ArrayType subArrayType = arrayType;
+ int start = subArrayType.getStartPosition();
+ if (this.ast.apiLevel() < AST.JLS8) {
+ while (extraDimensions > 0 ) {
+ subArrayType = (ArrayType) componentType(subArrayType);
+ extraDimensions--;
+ }
+ updateInnerPositions(subArrayType, remainingDimensions);
+ } else {
+ List dimensions = subArrayType.dimensions();
+ while (extraDimensions > 0 ) {
+ dimensions.remove(dimensions.size() - 1);
+ extraDimensions--;
+ }
+ }
+ int end = retrieveProperRightBracketPosition(remainingDimensions, start);
+ subArrayType.setSourceRange(start, end - start + 1);
+ // cut the child loose from its parent (without creating garbage)
+ subArrayType.setParent(null, null);
+ return subArrayType;
+ }
+
protected void setTypeForMethodDeclaration(MethodDeclaration methodDeclaration, Type type, int extraDimension) {
if (extraDimension != 0) {
if (type.isArrayType()) {
@@ -6116,18 +6157,7 @@ class ASTConverter {
break;
}
} else {
- int start = type.getStartPosition();
- ArrayType subarrayType = arrayType;
- int index = extraDimension;
- while (index > 0) {
- subarrayType = (ArrayType) subarrayType.getComponentType();
- index--;
- }
- int end = retrieveProperRightBracketPosition(remainingDimensions, start);
- subarrayType.setSourceRange(start, end - start + 1);
- // cut the child loose from its parent (without creating garbage)
- subarrayType.setParent(null, null);
- updateInnerPositions(subarrayType, remainingDimensions);
+ ArrayType subarrayType = extractSubArrayType(arrayType, remainingDimensions, extraDimension);
switch(this.ast.apiLevel) {
case AST.JLS2_INTERNAL :
methodDeclaration.internalSetReturnType(subarrayType);
@@ -6138,6 +6168,7 @@ class ASTConverter {
}
this.ast.getBindingResolver().updateKey(type, subarrayType);
}
+ checkAndSetMalformed(type, methodDeclaration);
} else {
switch(this.ast.apiLevel) {
case AST.JLS2_INTERNAL :
@@ -6177,21 +6208,12 @@ class ASTConverter {
this.ast.getBindingResolver().updateKey(type, elementType);
singleVariableDeclaration.setType(elementType);
} else {
- int start = type.getStartPosition();
- ArrayType subarrayType = arrayType;
- int index = extraDimension;
- while (index > 0) {
- subarrayType = (ArrayType) subarrayType.getComponentType();
- index--;
- }
- int end = retrieveProperRightBracketPosition(remainingDimensions, start);
- subarrayType.setSourceRange(start, end - start + 1);
- // cut the child loose from its parent (without creating garbage)
- subarrayType.setParent(null, null);
- updateInnerPositions(subarrayType, remainingDimensions);
- singleVariableDeclaration.setType(subarrayType);
+ ArrayType subarrayType = extractSubArrayType(arrayType, remainingDimensions, extraDimension);
this.ast.getBindingResolver().updateKey(type, subarrayType);
+ singleVariableDeclaration.setType(subarrayType);
}
+ checkAndSetMalformed(type, singleVariableDeclaration);
+
} else {
singleVariableDeclaration.setType(type);
}
@@ -6213,21 +6235,11 @@ class ASTConverter {
this.ast.getBindingResolver().updateKey(type, elementType);
variableDeclarationExpression.setType(elementType);
} else {
- int start = type.getStartPosition();
- ArrayType subarrayType = arrayType;
- int index = extraDimension;
- while (index > 0) {
- subarrayType = (ArrayType) subarrayType.getComponentType();
- index--;
- }
- int end = retrieveProperRightBracketPosition(remainingDimensions, start);
- subarrayType.setSourceRange(start, end - start + 1);
- // cut the child loose from its parent (without creating garbage)
- subarrayType.setParent(null, null);
- updateInnerPositions(subarrayType, remainingDimensions);
+ ArrayType subarrayType = extractSubArrayType(arrayType, remainingDimensions, extraDimension);
variableDeclarationExpression.setType(subarrayType);
this.ast.getBindingResolver().updateKey(type, subarrayType);
}
+ checkAndSetMalformed(type, variableDeclarationExpression);
} else {
variableDeclarationExpression.setType(type);
}
@@ -6249,21 +6261,11 @@ class ASTConverter {
this.ast.getBindingResolver().updateKey(type, elementType);
variableDeclarationStatement.setType(elementType);
} else {
- int start = type.getStartPosition();
- ArrayType subarrayType = arrayType;
- int index = extraDimension;
- while (index > 0) {
- subarrayType = (ArrayType) subarrayType.getComponentType();
- index--;
- }
- int end = retrieveProperRightBracketPosition(remainingDimensions, start);
- subarrayType.setSourceRange(start, end - start + 1);
- // cut the child loose from its parent (without creating garbage)
- subarrayType.setParent(null, null);
- updateInnerPositions(subarrayType, remainingDimensions);
+ ArrayType subarrayType = extractSubArrayType(arrayType, remainingDimensions, extraDimension);
variableDeclarationStatement.setType(subarrayType);
this.ast.getBindingResolver().updateKey(type, subarrayType);
}
+ checkAndSetMalformed(type, variableDeclarationStatement);
} else {
variableDeclarationStatement.setType(type);
}
@@ -6276,13 +6278,13 @@ class ASTConverter {
if (dimensions > 1) {
// need to set positions for intermediate array type see 42839
int start = type.getStartPosition();
- Type currentComponentType = ((ArrayType) type).getComponentType();
+ Type currentComponentType = componentType(((ArrayType) type));
int searchedDimension = dimensions - 1;
int rightBracketEndPosition = start;
while (currentComponentType.isArrayType()) {
rightBracketEndPosition = retrieveProperRightBracketPosition(searchedDimension, start);
currentComponentType.setSourceRange(start, rightBracketEndPosition - start + 1);
- currentComponentType = ((ArrayType) currentComponentType).getComponentType();
+ currentComponentType = componentType(((ArrayType) currentComponentType));
searchedDimension--;
}
}
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 23ca2f33c..87246dfbf 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
@@ -167,6 +167,13 @@ public class ASTMatcher {
}
/**
+ * @deprecated
+ */
+ private Type componentType(ArrayType array) {
+ return array.getComponentType();
+ }
+
+ /**
* Returns whether the given node and the other object match.
* <p>
* The default implementation provided by this class tests whether the
@@ -334,8 +341,11 @@ public class ASTMatcher {
}
ArrayType o = (ArrayType) other;
int level = node.getAST().apiLevel;
- return safeSubtreeMatch(node.getComponentType(), o.getComponentType())
- && (level >= AST.JLS8 ? safeSubtreeListMatch(node.annotations(), o.annotations()) : true);
+ if (level < AST.JLS8) {
+ return safeSubtreeMatch(componentType(node), componentType(o));
+ }
+ return safeSubtreeMatch(node.getElementType(), o.getElementType())
+ && safeSubtreeListMatch(node.dimensions(), o.dimensions());
}
/**
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
index cd1dd839d..c3e3f7543 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ArrayType.java
@@ -21,33 +21,42 @@ import java.util.List;
/**
* Type node for an array type.
* <p>
- * Array types are expressed in a recursive manner, one dimension at a time.
+ * Array types are expressed in a recursive manner, one dimension at a time. From JLS8 onwards,
+ * instead of this recursive manner, arrays are represented by a base element type (which cannot
+ * be an Array type) and a list of dimensions each of which may have a list of annotations.
* </p>
* <pre>
- * ArrayType:
- * Type { Annotation } <b>'['</b> <b>']'</b>
+ * ArrayType:
+ * Type ExtraDimension { ExtraDimension }
* </pre>
*
* @since 2.0
* @noinstantiate This class is not intended to be instantiated by clients.
*/
-public class ArrayType extends AnnotatableType {
+public class ArrayType extends Type {
/**
* The "componentType" structural property of this node type (child type: {@link Type}).
+ * Not supported from JLS8 onwards.
* @since 3.0
*/
public static final ChildPropertyDescriptor COMPONENT_TYPE_PROPERTY =
new ChildPropertyDescriptor(ArrayType.class, "componentType", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
/**
- * The "annotations" structural property of this node type (element type: {@link Annotation}).
+ * The "elementType" structural property of this node type (child type: {@link Type}) (added in JLS8 API).
* @since 3.9 BETA_JAVA8
*/
- public static final ChildListPropertyDescriptor ANNOTATIONS_PROPERTY =
- internalAnnotationsPropertyFactory(ArrayType.class);
+ public static final ChildPropertyDescriptor ELEMENT_TYPE_PROPERTY =
+ new ChildPropertyDescriptor(ArrayType.class, "elementType", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
/**
+ * The "dimensions" structural property of this node type (element type: {@link ExtraDimension}) (added in JLS8 API).
+ * @since 3.9 BETA_JAVA8
+ */
+ public static final ChildListPropertyDescriptor DIMENSIONS_PROPERTY =
+ new ChildListPropertyDescriptor(ArrayType.class, "dimensions", ExtraDimension.class, CYCLE_RISK); //$NON-NLS-1$
+ /**
* A list of property descriptors (element type:
* {@link StructuralPropertyDescriptor}),
* or null if uninitialized.
@@ -69,8 +78,8 @@ public class ArrayType extends AnnotatableType {
propertyList = new ArrayList(3);
createPropertyList(ArrayType.class, propertyList);
- addProperty(COMPONENT_TYPE_PROPERTY, propertyList);
- addProperty(ANNOTATIONS_PROPERTY, propertyList);
+ addProperty(ELEMENT_TYPE_PROPERTY, propertyList);
+ addProperty(DIMENSIONS_PROPERTY, propertyList);
PROPERTY_DESCRIPTORS_8_0 = reapPropertyList(propertyList);
}
@@ -98,11 +107,21 @@ public class ArrayType extends AnnotatableType {
/**
* The component type; lazily initialized; defaults to a simple type with
- * an unspecified, but legal, name.
+ * an unspecified, but legal, name. reused for element type from JLS8 onwards.
*/
private Type componentType = null;
/**
+ * List of extra dimensions this node has with optional annotations
+ * (element type: {@link ExtraDimension}).
+ * Null before JLS8. Added in JLS8; defaults to a list with one element
+ * (see constructor).
+ *
+ * @since 3.9 BETA_JAVA8
+ */
+ private ASTNode.NodeList dimensions = null;
+
+ /**
* Creates a new unparented node for an array type owned by the given AST.
* By default, a 1-dimensional array of an unspecified simple type.
* <p>
@@ -113,14 +132,31 @@ public class ArrayType extends AnnotatableType {
*/
ArrayType(AST ast) {
super(ast);
+ if (ast.apiLevel >= AST.JLS8) {
+ this.dimensions = new ASTNode.NodeList(DIMENSIONS_PROPERTY);
+ // single dimension array is the default
+ this.dimensions().add(this.ast.newExtraDimension());
+ }
}
- /* (omit javadoc for this method)
- * Method declared on AnnotatableType.
- * @since 3.9 BETA_JAVA8
- */
- final ChildListPropertyDescriptor internalAnnotationsProperty() {
- return ANNOTATIONS_PROPERTY;
+ /**
+ * Creates a new unparented node for an array type owned by the given AST.
+ * <p>
+ * N.B. This constructor is private.
+ * </p>
+ *
+ * @param ast the AST that is to own this node
+ * @param dimensions no of dimensions - can be zero
+ *
+ * @since 3.9 BETA_JAVA8
+ */
+ private ArrayType(AST ast, int dimensions) {
+ super(ast);
+ unsupportedIn2_3_4();
+ this.dimensions = new ASTNode.NodeList(DIMENSIONS_PROPERTY);
+ for (int i = 0; i < dimensions; ++i) {
+ this.dimensions().add(this.ast.newExtraDimension());
+ }
}
/* (omit javadoc for this method)
@@ -134,8 +170,8 @@ public class ArrayType extends AnnotatableType {
* Method declared on ASTNode.
*/
final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
- if (property == ANNOTATIONS_PROPERTY) {
- return annotations();
+ if (property == DIMENSIONS_PROPERTY) {
+ return dimensions();
}
// allow default implementation to flag the error
return super.internalGetChildListProperty(property);
@@ -152,6 +188,13 @@ public class ArrayType extends AnnotatableType {
setComponentType((Type) child);
return null;
}
+ } else if (property == ELEMENT_TYPE_PROPERTY) {
+ if (get) {
+ return getElementType();
+ } else {
+ setElementType((Type) child);
+ return null;
+ }
}
// allow default implementation to flag the error
return super.internalGetSetChildProperty(property, get, child);
@@ -168,13 +211,17 @@ public class ArrayType extends AnnotatableType {
* Method declared on ASTNode.
*/
ASTNode clone0(AST target) {
- ArrayType result = new ArrayType(target);
- result.setSourceRange(getStartPosition(), getLength());
- result.setComponentType((Type) getComponentType().clone(target));
- if (this.ast.apiLevel >= AST.JLS8) {
- result.annotations().addAll(
- ASTNode.copySubtrees(target, annotations()));
+ ArrayType result;
+ if (this.ast.apiLevel < AST.JLS8) {
+ result = new ArrayType(target);
+ result.setComponentType((Type) getComponentType().clone(target));
+ } else {
+ result = new ArrayType(target, 0);
+ result.setElementType((Type) getElementType().clone(target));
+ result.dimensions().addAll(
+ ASTNode.copySubtrees(target, dimensions()));
}
+ result.setSourceRange(getStartPosition(), getLength());
return result;
}
@@ -193,9 +240,11 @@ public class ArrayType extends AnnotatableType {
boolean visitChildren = visitor.visit(this);
if (visitChildren) {
// visit children in normal left to right reading order
- acceptChild(visitor, getComponentType());
- if (this.ast.apiLevel >= AST.JLS8) {
- acceptChildren(visitor, this.annotations);
+ if (this.ast.apiLevel < AST.JLS8) {
+ acceptChild(visitor, getComponentType());
+ } else {
+ acceptChild(visitor, getElementType());
+ acceptChildren(visitor, this.dimensions);
}
}
visitor.endVisit(this);
@@ -206,15 +255,21 @@ public class ArrayType extends AnnotatableType {
* may be another array type.
*
* @return the component type node
+ * @deprecated from JLS8 and later, the recursive structure is not valid
*/
public Type getComponentType() {
+ supportedOnlyIn2_3_4();
+ return internalGetComponentType(COMPONENT_TYPE_PROPERTY);
+ }
+
+ private Type internalGetComponentType(ChildPropertyDescriptor property) {
if (this.componentType == null) {
// lazy init must be thread-safe for readers
synchronized (this) {
if (this.componentType == null) {
preLazyInit();
this.componentType = new SimpleType(this.ast);
- postLazyInit(this.componentType, COMPONENT_TYPE_PROPERTY);
+ postLazyInit(this.componentType, property);
}
}
}
@@ -232,15 +287,21 @@ public class ArrayType extends AnnotatableType {
* <li>the node already has a parent</li>
* <li>a cycle in would be created</li>
* </ul>
+ * @deprecated from JLS8 and later, the recursive structure is not valid
*/
public void setComponentType(Type componentType) {
+ supportedOnlyIn2_3_4();
if (componentType == null) {
throw new IllegalArgumentException();
}
+ internalSetComponentType(componentType, COMPONENT_TYPE_PROPERTY);
+ }
+
+ private void internalSetComponentType(Type type, ChildPropertyDescriptor property) {
ASTNode oldChild = this.componentType;
- preReplaceChild(oldChild, componentType, COMPONENT_TYPE_PROPERTY);
- this.componentType = componentType;
- postReplaceChild(oldChild, componentType, COMPONENT_TYPE_PROPERTY);
+ preReplaceChild(oldChild, type, property);
+ this.componentType = type;
+ postReplaceChild(oldChild, type, property);
}
/**
@@ -248,36 +309,98 @@ public class ArrayType extends AnnotatableType {
* never an array type.
* <p>
* This is a convenience method that descends a chain of nested array types
- * until it reaches a non-array type.
+ * until it reaches a non-array type until JLS4. From JLS8 and later, this returns the
+ * element type directly.
* </p>
*
- * @return the component type node
+ * @return the element type node
*/
public Type getElementType() {
- Type t = getComponentType();
- while (t.isArrayType()) {
- t = ((ArrayType) t).getComponentType();
+ if (this.ast.apiLevel() < AST.JLS8) {
+ Type t = getComponentType();
+ while (t.isArrayType()) {
+ t = ((ArrayType) t).getComponentType();
+ }
+ return t;
}
- return t;
+ return internalGetComponentType(ELEMENT_TYPE_PROPERTY);
+ }
+
+ /**
+ * Sets the element type of the array.
+ *
+ * @param type the new type
+ * @exception IllegalArgumentException if:
+ * <ul>
+ * <li>the node belongs to a different AST</li>
+ * <li>the node already has a parent</li>
+ * <li>the node is an array type</li>
+ * </ul>
+ * @since 3.9 BETA_JAVA8
+ */
+ public void setElementType(Type type) {
+ if (type == null || type instanceof ArrayType) {
+ throw new IllegalArgumentException();
+ }
+ internalSetComponentType(type, ELEMENT_TYPE_PROPERTY);
}
/**
* Returns the number of dimensions in this array type.
* <p>
* This is a convenience method that descends a chain of nested array types
- * until it reaches a non-array type.
+ * until it reaches a non-array type (until JLS4). From JLS8 onwards,
+ * this returns the size of the dimensions list.
* </p>
*
* @return the number of dimensions (always positive)
*/
public int getDimensions() {
+ if (this.ast.apiLevel() >= AST.JLS8) {
+ return dimensions().size();
+ }
Type t = getComponentType();
- int dimensions = 1; // always include this array type
+ int dimension = 1; // always include this array type
while (t.isArrayType()) {
- dimensions++;
+ dimension++;
t = ((ArrayType) t).getComponentType();
}
- return dimensions;
+ return dimension;
+ }
+
+ /**
+ * Returns the dimension d in this array type.
+ * <p>
+ * This is a convenience method that returns the dimension at the given number d.
+ * </p>
+ * @param d dimension no
+ * @return Dimension at number d, null if d out of range
+ *
+ * @since 3.9 BETA_JAVA8
+ */
+ public ExtraDimension getDimensionAt(int d) {
+ unsupportedIn2_3_4();
+ ExtraDimension extraDimension = null;
+ int n = getDimensions() - 1;
+ if (d >= 0 && d <= n) {
+ extraDimension = (ExtraDimension) dimensions().get(n - d);
+ }
+ return extraDimension;
+ }
+
+ /**
+ * Returns the live ordered list of dimensions with optional annotations (added in JLS8 API).
+ *
+ * @return the live list of dimensions with optional annotations (element type: {@link ExtraDimension})
+ * @exception UnsupportedOperationException if this operation is used below JLS8
+ * @since 3.9 BETA_JAVA8
+ */
+ public List dimensions() {
+ // more efficient than just calling unsupportedIn2_3_4() to check
+ if (this.dimensions == null) {
+ unsupportedIn2_3_4();
+ }
+ return this.dimensions;
}
/* (omit javadoc for this method)
@@ -293,8 +416,8 @@ public class ArrayType extends AnnotatableType {
int treeSize() {
return
memSize()
- + (this.componentType == null ? 0 : getComponentType().treeSize())
- + (this.annotations == null ? 0 : this.annotations.listSize());
+ + (this.componentType == null ? 0 : (this.ast.apiLevel() < AST.JLS8 ? getComponentType().treeSize() : getElementType().treeSize())
+ + (this.dimensions == null ? 0 : this.dimensions.listSize()));
}
}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
index bb707a632..88abbed41 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
@@ -29,10 +29,10 @@ import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
-import org.eclipse.jdt.internal.compiler.ast.JavadocImplicitTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ImportReference;
import org.eclipse.jdt.internal.compiler.ast.JavadocAllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.JavadocFieldReference;
+import org.eclipse.jdt.internal.compiler.ast.JavadocImplicitTypeReference;
import org.eclipse.jdt.internal.compiler.ast.JavadocMessageSend;
import org.eclipse.jdt.internal.compiler.ast.JavadocQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.JavadocSingleNameReference;
@@ -926,7 +926,7 @@ class DefaultBindingResolver extends BindingResolver {
Object oldNode = this.newAstToOldAst.get(lambda);
if (oldNode instanceof org.eclipse.jdt.internal.compiler.ast.LambdaExpression) {
org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambdaExpression = (org.eclipse.jdt.internal.compiler.ast.LambdaExpression) oldNode;
- IMethodBinding methodBinding = getMethodBinding(lambdaExpression.binding);
+ IMethodBinding methodBinding = getMethodBinding(lambdaExpression.getMethodBinding());
if (methodBinding == null) {
return null;
}
@@ -977,7 +977,7 @@ class DefaultBindingResolver extends BindingResolver {
Object oldNode = this.newAstToOldAst.get(methodReference);
if (oldNode instanceof org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) {
org.eclipse.jdt.internal.compiler.ast.ReferenceExpression referenceExpression = (org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) oldNode;
- IMethodBinding methodBinding = getMethodBinding(referenceExpression.binding);
+ IMethodBinding methodBinding = getMethodBinding(referenceExpression.getMethodBinding());
if (methodBinding == null) {
return null;
}
@@ -1315,7 +1315,7 @@ class DefaultBindingResolver extends BindingResolver {
return method.getReturnType();
} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) {
org.eclipse.jdt.internal.compiler.ast.ReferenceExpression referenceExpression = (org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) node;
- IMethodBinding method = getMethodBinding(referenceExpression.binding);
+ IMethodBinding method = getMethodBinding(referenceExpression.getMethodBinding());
if (method == null) return null;
return method.getReturnType();
//{ObjectTeams: Resolve bindings for OT-specific elements
@@ -1607,7 +1607,7 @@ class DefaultBindingResolver extends BindingResolver {
return getMethodBinding(memberValuePair.binding);
} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) {
org.eclipse.jdt.internal.compiler.ast.ReferenceExpression referenceExpression = (org.eclipse.jdt.internal.compiler.ast.ReferenceExpression) node;
- return getMethodBinding(referenceExpression.binding);
+ return getMethodBinding(referenceExpression.getMethodBinding());
}
//{ObjectTeams: Resolve bindings for OT-specific elements
else if (node instanceof MethodSpec)
@@ -1800,7 +1800,11 @@ class DefaultBindingResolver extends BindingResolver {
}
ArrayType arrayType = (ArrayType) type;
ArrayBinding arrayBinding = (ArrayBinding) typeBinding;
- return getTypeBinding(this.scope.createArrayType(arrayBinding.leafComponentType, arrayType.getDimensions()));
+ int dimensions = arrayType.getDimensions();
+ boolean isVarargs = typeReference.isVarargs();
+ if (dimensions == arrayBinding.dimensions)
+ return getTypeBinding(arrayBinding); // reuse.
+ return getTypeBinding(this.scope.createArrayType(arrayBinding.leafComponentType, dimensions, getTypeAnnotations(dimensions, arrayBinding, isVarargs)));
}
if (typeBinding.isArrayType()) {
// 'typeBinding' can still be an array type because 'node' may be "larger" than 'type' (see comment of newAstToOldAst).
@@ -1826,7 +1830,9 @@ class DefaultBindingResolver extends BindingResolver {
binding = typeBinding;
}
} else if (node instanceof TypeReference) {
- if (type instanceof QualifiedType) {
+ if (type instanceof SimpleType && node instanceof QualifiedTypeReference) {
+ return resolveTypeBindingForName(((SimpleType)type).getName());
+ } else if (type instanceof QualifiedType) {
return resolveTypeBindingForName(((QualifiedType)type).getName());
} else if (type instanceof PackageQualifiedType){
return resolveTypeBindingForName(((PackageQualifiedType)type).getName());
@@ -1847,7 +1853,11 @@ class DefaultBindingResolver extends BindingResolver {
return null;
}
ArrayBinding arrayBinding = (ArrayBinding) binding;
- return getTypeBinding(this.scope.createArrayType(arrayBinding.leafComponentType, arrayType.getDimensions()));
+ int dimensions = arrayType.getDimensions();
+ boolean isVarargs = node instanceof TypeReference && ((TypeReference) node).isVarargs();
+ if (dimensions == arrayBinding.dimensions)
+ return getTypeBinding(arrayBinding); // reuse
+ return getTypeBinding(this.scope.createArrayType(arrayBinding.leafComponentType, dimensions, getTypeAnnotations(dimensions, arrayBinding, isVarargs)));
} else if (binding.isArrayType()) {
// 'binding' can still be an array type because 'node' may be "larger" than 'type' (see comment of newAstToOldAst).
ArrayBinding arrayBinding = (ArrayBinding) binding;
@@ -1866,6 +1876,27 @@ class DefaultBindingResolver extends BindingResolver {
return null;
}
+ private org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] getTypeAnnotations(int dimensions, ArrayBinding arrayBinding, boolean isVarargs) {
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding [] oldies = arrayBinding.getTypeAnnotations();
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] newbies = Binding.NO_ANNOTATIONS;
+ // Skip past extended dimensions encoded ahead of base dimensions. Dimension for variable argument array comes after the base dimensions.
+ int extendedDimensions = arrayBinding.dimensions - dimensions - (isVarargs ? 1 : 0);
+ int i, length;
+ for (i = 0, length = oldies == null ? 0 : oldies.length; i < length && extendedDimensions > 0 ; i++) {
+ if (oldies[i] == null)
+ extendedDimensions--;
+ }
+ int cells = 0;
+ for (int j = i; j < length && dimensions > 0 ; j++) {
+ if (oldies[j] == null)
+ dimensions--;
+ cells ++;
+ }
+ if (cells > 0)
+ System.arraycopy(oldies, i, newbies = new org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[cells], 0, cells);
+ return newbies;
+ }
+
/*
* Method declared on BindingResolver.
*/
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
index 0adf7bfe6..88bda366f 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ITypeBinding.java
@@ -17,7 +17,6 @@
package org.eclipse.jdt.core.dom;
-
/**
* <h4>OTDT changes:</h4>
* <dl>
@@ -101,7 +100,7 @@ public interface ITypeBinding extends IBinding {
* @since 3.1
*/
public ITypeBinding getBound();
-
+
/**
* Returns the generic type associated with this wildcard type, if it has one.
* Returns <code>null</code> if this is not a wildcard type.
@@ -122,7 +121,7 @@ public interface ITypeBinding extends IBinding {
* @since 3.5
*/
public int getRank();
-
+
/**
* Returns the binding representing the component type of this array type,
* or <code>null</code> if this is not an array type binding. The component
@@ -279,6 +278,17 @@ public interface ITypeBinding extends IBinding {
public ITypeBinding getElementType();
/**
+ * Returns the binding representing the enclosing type of this type,
+ * or <code>null</code> if the receiver is an array type binding or a top level
+ * type or a primitive type.
+ *
+ * @return the enclosing type binding, or <code>null</code> if this is
+ * an array type, or a primitive type or a top level type.
+ * @since 3.9 BETA_JAVA8
+ */
+ public ITypeBinding getEnclosingType();
+
+ /**
* Returns the erasure of this type binding.
* <ul>
* <li>For parameterized types ({@link #isParameterizedType()})
@@ -1043,6 +1053,24 @@ public interface ITypeBinding extends IBinding {
*/
public boolean isWildcardType();
+ /**
+ * Returns the annotations that this type reference is annotated with. Since JLS8,
+ * multiple instances of type bindings may be created if they are annotated with
+ * different type use annotations.
+ * <p>
+ * For example, the following two type references would produce two distinct type
+ * bindings for java.lang.String.
+ * <ul>
+ * <li>java.lang.@Marker1 String</li>
+ * <li>java.lang.@Marker2 String</li>
+ * </ul>
+ * </p>
+ * @return type annotations specified on this type reference, or an empty array if
+ * no type use annotations are found.
+ * @since 3.9 BETA_JAVA8
+ */
+ public IAnnotationBinding[] getTypeAnnotations();
+
//{ObjectTeams: new queries
/**
* Returns whether this type binding represents a dependent type.
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 95713d6c7..bff3984e0 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
@@ -197,6 +197,14 @@ class RecoveredTypeBinding implements ITypeBinding {
}
return null;
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getEnclosingType()
+ */
+
+ public ITypeBinding getEnclosingType() {
+ return null;
+ }
/* (non-Javadoc)
* @see org.eclipse.jdt.core.dom.ITypeBinding#getErasure()
@@ -764,6 +772,10 @@ class RecoveredTypeBinding implements ITypeBinding {
}
return null; // should not happen
}
+
+ public IAnnotationBinding[] getTypeAnnotations() {
+ return AnnotationBinding.NoAnnotations;
+ }
//{ObjectTeams: new lookup-functions
public org.eclipse.jdt.internal.compiler.lookup.TypeBinding getResolvedBinding() {
return this.binding;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
index bad9575b7..04831e337 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeBinding.java
@@ -78,10 +78,12 @@ class TypeBinding implements ITypeBinding {
Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | Modifier.STRICTFP;
org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding;
+ private TypeBinding prototype = null;
private String key;
private BindingResolver resolver;
private IVariableBinding[] fields;
private IAnnotationBinding[] annotations;
+ private IAnnotationBinding[] typeAnnotations;
private IMethodBinding[] methods;
private ITypeBinding[] members;
private ITypeBinding[] interfaces;
@@ -92,6 +94,8 @@ class TypeBinding implements ITypeBinding {
public TypeBinding(BindingResolver resolver, org.eclipse.jdt.internal.compiler.lookup.TypeBinding binding) {
this.binding = binding;
this.resolver = resolver;
+ org.eclipse.jdt.internal.compiler.lookup.TypeBinding compilerPrototype = binding.prototype();
+ this.prototype = (TypeBinding) (compilerPrototype == null || compilerPrototype == binding ? null : resolver.getTypeBinding(compilerPrototype));
}
public ITypeBinding createArrayType(int dimension) {
@@ -104,6 +108,9 @@ class TypeBinding implements ITypeBinding {
}
public IAnnotationBinding[] getAnnotations() {
+ if (this.prototype != null) {
+ return this.prototype.getAnnotations();
+ }
if (this.annotations != null) {
return this.annotations;
}
@@ -126,28 +133,35 @@ class TypeBinding implements ITypeBinding {
Dependencies.release(this);
}
// SH}
- int length = internalAnnotations == null ? 0 : internalAnnotations.length;
- if (length != 0) {
- IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
- int convertedAnnotationCount = 0;
- for (int i = 0; i < length; i++) {
- org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
- IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
- if (annotationInstance == null) {
- continue;
- }
- tempAnnotations[convertedAnnotationCount++] = annotationInstance;
+ return this.annotations = resolveAnnotationBindings(refType.getAnnotations(), false);
+ }
+ return this.annotations = AnnotationBinding.NoAnnotations;
+ }
+ private IAnnotationBinding[] resolveAnnotationBindings(org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding[] internalAnnotations, boolean isTypeUse) {
+ int length = internalAnnotations == null ? 0 : internalAnnotations.length;
+ if (length != 0) {
+ IAnnotationBinding[] tempAnnotations = new IAnnotationBinding[length];
+ int convertedAnnotationCount = 0;
+ for (int i = 0; i < length; i++) {
+ org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding internalAnnotation = internalAnnotations[i];
+ if (isTypeUse && internalAnnotation == null) {
+ break;
}
- if (convertedAnnotationCount != length) {
- if (convertedAnnotationCount == 0) {
- return this.annotations = AnnotationBinding.NoAnnotations;
- }
- System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
+ IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
+ if (annotationInstance == null) {
+ continue;
+ }
+ tempAnnotations[convertedAnnotationCount++] = annotationInstance;
+ }
+ if (convertedAnnotationCount != length) {
+ if (convertedAnnotationCount == 0) {
+ return this.annotations = AnnotationBinding.NoAnnotations;
}
- return this.annotations = tempAnnotations;
+ System.arraycopy(tempAnnotations, 0, (tempAnnotations = new IAnnotationBinding[convertedAnnotationCount]), 0, convertedAnnotationCount);
}
+ return tempAnnotations;
}
- return this.annotations = AnnotationBinding.NoAnnotations;
+ return AnnotationBinding.NoAnnotations;
}
/*
@@ -250,6 +264,9 @@ class TypeBinding implements ITypeBinding {
* @see ITypeBinding#getDeclaredFields()
*/
public synchronized IVariableBinding[] getDeclaredFields() {
+ if (this.prototype != null) {
+ return this.prototype.getDeclaredFields();
+ }
if (this.fields != null) {
return this.fields;
}
@@ -310,6 +327,9 @@ class TypeBinding implements ITypeBinding {
* @see ITypeBinding#getDeclaredMethods()
*/
public synchronized IMethodBinding[] getDeclaredMethods() {
+ if (this.prototype != null) {
+ return this.prototype.getDeclaredMethods();
+ }
if (this.methods != null) {
return this.methods;
}
@@ -379,7 +399,7 @@ class TypeBinding implements ITypeBinding {
/*
* @see ITypeBinding#getDeclaredTypes()
*/
- public synchronized ITypeBinding[] getDeclaredTypes() {
+ public synchronized ITypeBinding[] getDeclaredTypes() { // should not deflect to prototype.
if (this.members != null) {
return this.members;
}
@@ -518,6 +538,13 @@ class TypeBinding implements ITypeBinding {
}
/* (non-Javadoc)
+ * @see org.eclipse.jdt.core.dom.ITypeBinding#getEnclosingType()
+ */
+ public ITypeBinding getEnclosingType() {
+ return this.resolver.getTypeBinding(this.binding.enclosingType());
+ }
+
+ /* (non-Javadoc)
* @see org.eclipse.jdt.core.dom.ITypeBinding#getErasure()
*/
public ITypeBinding getErasure() {
@@ -525,6 +552,9 @@ class TypeBinding implements ITypeBinding {
}
public synchronized ITypeBinding[] getInterfaces() {
+ if (this.prototype != null) {
+ return this.prototype.getInterfaces();
+ }
if (this.interfaces != null) {
return this.interfaces;
}
@@ -987,6 +1017,9 @@ class TypeBinding implements ITypeBinding {
* @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeArguments()
*/
public ITypeBinding[] getTypeArguments() {
+ if (this.prototype != null) {
+ return this.prototype.getTypeArguments();
+ }
if (this.typeArguments != null) {
return this.typeArguments;
}
@@ -1011,6 +1044,9 @@ class TypeBinding implements ITypeBinding {
* @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeBounds()
*/
public ITypeBinding[] getTypeBounds() {
+ if (this.prototype != null) {
+ return this.prototype.getTypeBounds();
+ }
if (this.bounds != null) {
return this.bounds;
}
@@ -1063,6 +1099,9 @@ class TypeBinding implements ITypeBinding {
* @see org.eclipse.jdt.core.dom.ITypeBinding#getTypeParameters()
*/
public ITypeBinding[] getTypeParameters() {
+ if (this.prototype != null) {
+ return this.prototype.getTypeParameters();
+ }
if (this.typeParameters != null) {
return this.typeParameters;
}
@@ -1238,6 +1277,9 @@ class TypeBinding implements ITypeBinding {
return false;
}
org.eclipse.jdt.internal.compiler.lookup.TypeBinding otherBinding = ((TypeBinding) other).binding;
+ if (otherBinding.unannotated() == this.binding.unannotated()) {
+ return true;
+ }
// check return type
return BindingComparator.isEqual(this.binding, otherBinding);
}
@@ -1577,4 +1619,15 @@ class TypeBinding implements ITypeBinding {
public String toString() {
return this.binding.toString();
}
+
+ /*
+ * @see ITypeBinding#getTypeUseAnnotations()
+ */
+ public IAnnotationBinding[] getTypeAnnotations() {
+ if (this.typeAnnotations != null) {
+ return this.typeAnnotations;
+ }
+ this.typeAnnotations = resolveAnnotationBindings(this.binding.getTypeAnnotations(), true);
+ return this.typeAnnotations;
+ }
}
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 3a1f4b5a3..58eb31853 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
@@ -372,9 +372,17 @@ public class NaiveASTFlattener extends ASTVisitor {
* @see ASTVisitor#visit(ArrayType)
*/
public boolean visit(ArrayType node) {
- node.getComponentType().accept(this);
- visitTypeAnnotations(node);
- this.buffer.append("[]");//$NON-NLS-1$
+ if (node.getAST().apiLevel() < AST.JLS8) {
+ visitComponentType(node);
+ this.buffer.append("[]");//$NON-NLS-1$
+ } else {
+ node.getElementType().accept(this);
+ List dimensions = node.dimensions();
+ for (int i = 0; i < dimensions.size() ; i++) {
+ ExtraDimension aDimension = (ExtraDimension) dimensions.get(i);
+ aDimension.accept(this);
+ }
+ }
return false;
}
@@ -1963,6 +1971,13 @@ public class NaiveASTFlattener extends ASTVisitor {
return false;
}
+ /**
+ * @deprecated
+ */
+ private void visitComponentType(ArrayType node) {
+ node.getComponentType().accept(this);
+ }
+
//{ObjectTeams: visit methods for OT-specific types
/*
* @see ASTVisitor#visit(MethodSpec)
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
index daccaa1fa..5ac1b0617 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteAnalyzer.java
@@ -2105,15 +2105,15 @@ public final class ASTRewriteAnalyzer extends ASTVisitor {
RewriteEvent dimEvent= getEvent(node, ArrayCreation.DIMENSIONS_PROPERTY);
boolean hasDimensionChanges= (dimEvent != null && dimEvent.getChangeKind() != RewriteEvent.UNCHANGED);
RewriteEvent[] events= hasDimensionChanges ? dimEvent.getChildren() : null;
- ArrayType currentLevel= (ArrayType) replacingType.getElementType().getParent();
+ boolean astLevelGTE8 = node.getAST().apiLevel() >= AST.JLS8 ? true : false;
+ ArrayType currentLevel = astLevelGTE8 ? null : (ArrayType) replacingType.getElementType().getParent();
+ int replacingTypeDimensions = replacingType.getDimensions();
int i=0, dimSize= (events == null) ? 0 : events.length;
Type elementType= arrayType.getElementType();
int offset= elementType.getStartPosition() + elementType.getLength();
- while(currentLevel != null) {
- if (node.getAST().apiLevel() >= AST.JLS8) {
- rewriteTypeAnnotations(currentLevel, ArrayType.ANNOTATIONS_PROPERTY, offset);
- }
+ while(currentLevel != null || astLevelGTE8) {
if (i < dimSize) {
+ if (astLevelGTE8) internalExtraDimensionRewrite(replacingType, i, offset);
offset= getScanner().getTokenEndOffset(TerminalTokens.TokenNameLBRACKET, offset);
if (hasDimensionChanges) {
RewriteEvent event= events[i];
@@ -2148,13 +2148,19 @@ public final class ASTRewriteAnalyzer extends ASTVisitor {
offset= retrieveRightBracketEndPosition(offset, 1, true);
}
} else if (i < nOldBrackets) {
+ if (astLevelGTE8) internalExtraDimensionRewrite(replacingType, i, offset);
offset= retrieveRightBracketEndPosition(offset, 1, false);
} else {
+ internalExtraDimensionAddition(replacingType, i, offset, editGroup, astLevelGTE8);
doTextInsert(offset, "[]", editGroup); //$NON-NLS-1$
}
i++;
- if (currentLevel == replacingType) break;
- currentLevel= (ArrayType) currentLevel.getParent();
+ if (astLevelGTE8) {
+ if (i == replacingTypeDimensions) break;
+ } else {
+ if (currentLevel == replacingType) break;
+ currentLevel= (ArrayType) currentLevel.getParent();
+ }
}
if (i < nOldBrackets) {
int endPos= retrieveRightBracketEndPosition(offset, nOldBrackets - i, false);
@@ -2174,6 +2180,26 @@ public final class ASTRewriteAnalyzer extends ASTVisitor {
return false;
}
+ private void internalExtraDimensionAddition(ArrayType replacingType, int index, int pos, TextEditGroup editGroup,
+ boolean astLevelGTE8) {
+ if (astLevelGTE8) {
+ ExtraDimension dim = (ExtraDimension) replacingType.dimensions().get(index);
+ List annotations = dim.annotations();
+ if (annotations != null) {
+ for (int j = 0; j < annotations.size(); j++) {
+ Annotation annotation = (Annotation) annotations.get(j);
+ doTextInsert(pos, annotation.toString() + " ", editGroup); //$NON-NLS-1$
+ }
+
+ }
+ }
+ }
+
+ private void internalExtraDimensionRewrite(ArrayType replacingType, int index, int pos) {
+ ExtraDimension dim = (ExtraDimension) replacingType.dimensions().get(index);
+ rewriteTypeAnnotations(dim, ExtraDimension.ANNOTATIONS_PROPERTY, pos);
+ }
+
/**
* This method is used to retrieve the position of the right bracket.
* @return int the dimension found, -1 if none
@@ -2203,6 +2229,9 @@ public final class ASTRewriteAnalyzer extends ASTVisitor {
}
private Type getElementType(ArrayType parent) {
+ if (parent.getAST().apiLevel() >= AST.JLS8) {
+ return (Type) getOriginalValue(parent, ArrayType.ELEMENT_TYPE_PROPERTY);
+ }
Type t = (Type) getOriginalValue(parent, ArrayType.COMPONENT_TYPE_PROPERTY);
while (t.isArrayType()) {
t = (Type) getOriginalValue(t, ArrayType.COMPONENT_TYPE_PROPERTY);
@@ -2211,6 +2240,9 @@ public final class ASTRewriteAnalyzer extends ASTVisitor {
}
private int getDimensions(ArrayType parent) {
+ if (parent.getAST().apiLevel() >= AST.JLS8) {
+ return ((List) getOriginalValue(parent, ArrayType.DIMENSIONS_PROPERTY)).size();
+ }
Type t = (Type) getOriginalValue(parent, ArrayType.COMPONENT_TYPE_PROPERTY);
int dimensions = 1; // always include this array type
while (t.isArrayType()) {
@@ -2242,9 +2274,11 @@ public final class ASTRewriteAnalyzer extends ASTVisitor {
if (!hasChildrenChanges(node)) {
return doVisitUnchangedChildren(node);
}
- int pos = rewriteRequiredNode(node, ArrayType.COMPONENT_TYPE_PROPERTY);
- if (node.getAST().apiLevel() >= AST.JLS8) {
- rewriteTypeAnnotations(node, ArrayType.ANNOTATIONS_PROPERTY, pos);
+ if (node.getAST().apiLevel() < AST.JLS8) {
+ rewriteRequiredNode(node, ArrayType.COMPONENT_TYPE_PROPERTY);
+ } else {
+ int pos = rewriteRequiredNode(node, ArrayType.ELEMENT_TYPE_PROPERTY);
+ rewriteNodeList(node, ArrayType.DIMENSIONS_PROPERTY, pos, Util.EMPTY_STRING, " "); //$NON-NLS-1$
}
return false;
}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java
index 709b6d52c..b556362fa 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFlattener.java
@@ -270,35 +270,35 @@ public class ASTRewriteFlattener extends ASTVisitor {
ArrayType arrayType= (ArrayType) getChildNode(node, ArrayCreation.TYPE_PROPERTY);
// get the element type and count dimensions
- Type elementType= (Type) getChildNode(arrayType, ArrayType.COMPONENT_TYPE_PROPERTY);
- int dimensions= 1; // always include this array type
- while (elementType.isArrayType()) {
- dimensions++;
- elementType = (Type) getChildNode(elementType, ArrayType.COMPONENT_TYPE_PROPERTY);
+ Type elementType;
+ int dimensions;
+ boolean astLevelGTE8 = node.getAST().apiLevel() >= AST.JLS8 ? true : false;
+ if (astLevelGTE8) {
+ elementType = (Type) getChildNode(arrayType, ArrayType.ELEMENT_TYPE_PROPERTY);
+ dimensions = getChildList(arrayType, ArrayType.DIMENSIONS_PROPERTY).size();
+ } else {
+ elementType = (Type) getChildNode(arrayType, ArrayType.COMPONENT_TYPE_PROPERTY);
+ dimensions = 1; // always include this array type
+ while (elementType.isArrayType()) {
+ dimensions++;
+ elementType = (Type) getChildNode(elementType, ArrayType.COMPONENT_TYPE_PROPERTY);
+ }
}
elementType.accept(this);
// add "<annotations> [ <dimension> ]" for each dimension expression
- Type type= arrayType;
List list= getChildList(node, ArrayCreation.DIMENSIONS_PROPERTY);
for (int i= 0; i < list.size(); i++) {
- if (node.getAST().apiLevel() >= AST.JLS8 && type instanceof ArrayType) {
- visitList(type, ArrayType.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
- type = (Type) getChildNode(type, ArrayType.COMPONENT_TYPE_PROPERTY);
- }
+ internalVisitExtraDimensionAnnotations(arrayType, i, astLevelGTE8);
this.result.append('[');
((ASTNode) list.get(i)).accept(this);
this.result.append(']');
- dimensions--;
}
// add "<annotations> []" for each extra array dimension
- for (int i= 0; i < dimensions; i++) {
- if (node.getAST().apiLevel() >= AST.JLS8 && type instanceof ArrayType) {
- visitList(type, ArrayType.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
- type = (Type) getChildNode(type, ArrayType.COMPONENT_TYPE_PROPERTY);
- }
+ for (int i= list.size(); i < dimensions; i++) {
+ internalVisitExtraDimensionAnnotations(arrayType, i, astLevelGTE8);
this.result.append("[]"); //$NON-NLS-1$
}
@@ -309,6 +309,13 @@ public class ASTRewriteFlattener extends ASTVisitor {
return false;
}
+ private void internalVisitExtraDimensionAnnotations(ArrayType arrayType, int index, boolean astLevelGTE8) {
+ if (astLevelGTE8) {
+ ExtraDimension extraDimension = (ExtraDimension) arrayType.dimensions().get(index);
+ visitList(extraDimension, ExtraDimension.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ }
+ }
+
/*
* @see ASTVisitor#visit(ArrayInitializer)
*/
@@ -323,11 +330,13 @@ public class ASTRewriteFlattener extends ASTVisitor {
* @see ASTVisitor#visit(ArrayType)
*/
public boolean visit(ArrayType node) {
- getChildNode(node, ArrayType.COMPONENT_TYPE_PROPERTY).accept(this);
- if (node.getAST().apiLevel() >= AST.JLS8) {
- visitList(node, ArrayType.ANNOTATIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
+ if (node.getAST().apiLevel() < AST.JLS8) {
+ getChildNode(node, ArrayType.COMPONENT_TYPE_PROPERTY).accept(this);
+ this.result.append("[]"); //$NON-NLS-1$
+ } else {
+ getChildNode(node, ArrayType.ELEMENT_TYPE_PROPERTY).accept(this);
+ visitList(node, ArrayType.DIMENSIONS_PROPERTY, String.valueOf(' '), Util.EMPTY_STRING, String.valueOf(' '));
}
- this.result.append("[]"); //$NON-NLS-1$
return false;
}
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java
index 0e7c4325f..b9a0a33f8 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/internal/core/dom/rewrite/ASTRewriteFormatter.java
@@ -49,7 +49,7 @@ import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
-/* package */ final class ASTRewriteFormatter {
+public final class ASTRewriteFormatter {
public static class NodeMarker extends Position {
public Object data;
diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java
index 12dc92810..096e5e9a8 100644
--- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java
+++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetParser.java
@@ -269,11 +269,11 @@ protected void consumeLocalVariableDeclarationStatement() {
* The CSToCuMapper could not be used, since it could have interfered with
* the syntax recovery specific to code snippets.
*/
-protected void consumeMethodDeclaration(boolean isNotAbstract) {
+protected void consumeMethodDeclaration(boolean isNotAbstract, boolean isDefaultMethod) {
// MethodDeclaration ::= MethodHeader MethodBody
// AbstractMethodDeclaration ::= MethodHeader ';'
- super.consumeMethodDeclaration(isNotAbstract);
+ super.consumeMethodDeclaration(isNotAbstract, isDefaultMethod);
// now we know that we have a method declaration at the top of the ast stack
MethodDeclaration methodDecl = (MethodDeclaration) this.astStack[this.astPtr];
@@ -320,7 +320,7 @@ protected void consumeMethodDeclaration(boolean isNotAbstract) {
}
int dimCount = CharOperation.occurencesOf('[', this.evaluationContext.localVariableTypeNames[i]);
if (dimCount > 0) {
- typeReference = copyDims(typeReference, dimCount);
+ typeReference = augmentTypeWithAdditionalDimensions(typeReference, dimCount, null, false);
}
NameReference init = new SingleNameReference(
CharOperation.concat(LOCAL_VAR_PREFIX, this.evaluationContext.localVariableNames[i]), position);
@@ -598,7 +598,7 @@ protected CompilationUnitDeclaration endParse(int act) {
}
consumeMethodBody();
if (!this.diet) {
- consumeMethodDeclaration(true);
+ consumeMethodDeclaration(true, false);
if (fieldsCount > 0) {
consumeClassBodyDeclarations();
}
diff --git a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
index 168323b51..47f03d96a 100644
--- a/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
+++ b/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java
@@ -877,7 +877,7 @@ public class CodeFormatterVisitor extends ASTVisitor {
if (this.preferences.insert_space_before_opening_bracket_in_array_type_reference) {
this.scribe.space();
}
- Annotation[][] annotationsOnDimensions = typeReference != null ? typeReference.getAnnotationsOnDimensions() : null;
+ Annotation[][] annotationsOnDimensions = typeReference != null ? typeReference.getAnnotationsOnDimensions(true) : null;
for (int i = 0; i < count; i++) {
int dimensionIndex = anchor + i;
if (annotationsOnDimensions != null && annotationsOnDimensions.length > dimensionIndex) {
@@ -3010,7 +3010,7 @@ public class CodeFormatterVisitor extends ASTVisitor {
}
if (argument.isVarArgs()) {
- Annotation [][] annotationsOnDimensions = argumentType.getAnnotationsOnDimensions();
+ Annotation [][] annotationsOnDimensions = argumentType.getAnnotationsOnDimensions(true);
if (annotationsOnDimensions != null) {
Annotation [] varargAnnotations = annotationsOnDimensions[annotationsOnDimensions.length - 1];
if (varargAnnotations != null) {
diff --git a/org.eclipse.jdt.core/grammar/java.g b/org.eclipse.jdt.core/grammar/java.g
index 81fe9cca7..ab7b02111 100644
--- a/org.eclipse.jdt.core/grammar/java.g
+++ b/org.eclipse.jdt.core/grammar/java.g
@@ -850,12 +850,17 @@ VariableInitializer -> ArrayInitializer
MethodDeclaration -> AbstractMethodDeclaration
MethodDeclaration ::= MethodHeader MethodBody
/.$putCase // set to true to consume a method with a body
- consumeMethodDeclaration(true); $break ./
+ consumeMethodDeclaration(true, false); $break ./
+/:$readableName MethodDeclaration:/
+
+MethodDeclaration ::= DefaultMethodHeader MethodBody
+/.$putCase // set to true to consume a method with a body
+ consumeMethodDeclaration(true, true); $break ./
/:$readableName MethodDeclaration:/
AbstractMethodDeclaration ::= MethodHeader ';'
/.$putCase // set to false to consume a method without body
- consumeMethodDeclaration(false); $break ./
+ consumeMethodDeclaration(false, false); $break ./
/:$readableName MethodDeclaration:/
MethodHeader ::= MethodHeaderName FormalParameterListopt MethodHeaderRightParen MethodHeaderExtendedDims MethodHeaderThrowsClauseopt
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
index 1049a82f1..ea8d0f104 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/DocumentElementParser.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 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
@@ -471,7 +471,6 @@ protected void consumeEnterVariable() {
this.identifierLengthPtr--;
TypeReference type;
int variableIndex = this.variablesCounter[this.nestedType];
- int typeDim = 0;
if (variableIndex == 0) {
// first variable of the declaration (FieldDeclaration or LocalDeclaration)
if (this.nestedMethod[this.nestedType] != 0) {
@@ -479,11 +478,11 @@ protected void consumeEnterVariable() {
declaration.declarationSourceStart = this.intStack[this.intPtr--];
declaration.modifiersSourceStart = this.intStack[this.intPtr--];
declaration.modifiers = this.intStack[this.intPtr--];
- type = getTypeReference(typeDim = this.intStack[this.intPtr--]); // type dimension
+ type = getTypeReference(this.intStack[this.intPtr--]); // type dimension
pushOnAstStack(type);
} else {
// field declaration
- type = getTypeReference(typeDim = this.intStack[this.intPtr--]); // type dimension
+ type = getTypeReference(this.intStack[this.intPtr--]); // type dimension
pushOnAstStack(type);
declaration.declarationSourceStart = this.intStack[this.intPtr--];
declaration.modifiersSourceStart = this.intStack[this.intPtr--];
@@ -501,7 +500,6 @@ protected void consumeEnterVariable() {
}
} else {
type = (TypeReference) this.astStack[this.astPtr - variableIndex];
- typeDim = type.dimensions();
AbstractVariableDeclaration previousVariable =
(AbstractVariableDeclaration) this.astStack[this.astPtr];
declaration.declarationSourceStart = previousVariable.declarationSourceStart;
@@ -514,17 +512,9 @@ protected void consumeEnterVariable() {
}
}
- if (extendedTypeDimension == 0) {
- declaration.type = type;
- } else {
- int dimension = typeDim + extendedTypeDimension;
- Annotation [][] annotationsOnAllDimensions = null;
- Annotation[][] annotationsOnDimensions = type.getAnnotationsOnDimensions();
- if (annotationsOnDimensions != null || annotationsOnExtendedDimensions != null) {
- annotationsOnAllDimensions = getMergedAnnotationsOnDimensions(typeDim, annotationsOnDimensions, extendedTypeDimension, annotationsOnExtendedDimensions);
- }
- declaration.type = copyDims(type, dimension, annotationsOnAllDimensions);
- }
+ declaration.type = extendedTypeDimension != 0 ? augmentTypeWithAdditionalDimensions(type, extendedTypeDimension, annotationsOnExtendedDimensions, false) : type;
+ declaration.bits |= (type.bits & ASTNode.HasTypeAnnotations);
+
this.variablesCounter[this.nestedType]++;
this.nestedMethod[this.nestedType]++;
pushOnAstStack(declaration);
@@ -748,19 +738,13 @@ protected void consumeFormalParameter(boolean isVarArgs) {
int firstDimensions = this.intStack[this.intPtr--];
TypeReference type = getTypeReference(firstDimensions);
- final int typeDimensions = firstDimensions + extendedDimensions + (isVarArgs ? 1 : 0);
- if (typeDimensions != firstDimensions) {
- // jsr308 type annotations management
- Annotation [][] annotationsOnFirstDimensions = firstDimensions == 0 ? null : type.getAnnotationsOnDimensions();
- Annotation [][] annotationsOnAllDimensions = annotationsOnFirstDimensions;
- if (annotationsOnExtendedDimensions != null) {
- annotationsOnAllDimensions = getMergedAnnotationsOnDimensions(firstDimensions, annotationsOnFirstDimensions, extendedDimensions, annotationsOnExtendedDimensions);
- }
- if (varArgsAnnotations != null) {
- annotationsOnAllDimensions = getMergedAnnotationsOnDimensions(firstDimensions + extendedDimensions, annotationsOnAllDimensions,
- 1, new Annotation[][]{varArgsAnnotations});
+ if (isVarArgs || extendedDimensions != 0) {
+ if (isVarArgs) {
+ type = augmentTypeWithAdditionalDimensions(type, 1, varArgsAnnotations != null ? new Annotation[][] { varArgsAnnotations } : null, true);
+ }
+ if (extendedDimensions != 0) { // combination illegal.
+ type = augmentTypeWithAdditionalDimensions(type, extendedDimensions, annotationsOnExtendedDimensions, false);
}
- type = copyDims(type, typeDimensions, annotationsOnAllDimensions);
type.sourceEnd = type.isParameterizedTypeReference() ? this.endStatementPosition : this.endPosition;
}
if (isVarArgs) {
@@ -942,10 +926,10 @@ protected void consumeLocalVariableDeclaration() {
*
* INTERNAL USE-ONLY
*/
-protected void consumeMethodDeclaration(boolean isNotAbstract) {
+protected void consumeMethodDeclaration(boolean isNotAbstract, boolean isDefaultMethod) {
// MethodDeclaration ::= MethodHeader MethodBody
// AbstractMethodDeclaration ::= MethodHeader ';'
- super.consumeMethodDeclaration(isNotAbstract);
+ super.consumeMethodDeclaration(isNotAbstract, isDefaultMethod);
if (isLocalDeclaration()) {
// we ignore the local variable declarations
return;
@@ -1045,17 +1029,8 @@ protected void consumeMethodHeaderExtendedDims() {
int extendedDims = this.intStack[this.intPtr--];
this.extendsDim = extendedDims;
if (extendedDims != 0) {
- TypeReference returnType = md.returnType;
md.sourceEnd = this.endPosition;
- int dims = returnType.dimensions() + extendedDims;
- Annotation [][] annotationsOnDimensions = returnType.getAnnotationsOnDimensions();
- Annotation [][] annotationsOnExtendedDimensions = getAnnotationsOnDimensions(extendedDims);
- Annotation [][] annotationsOnAllDimensions = null;
- if (annotationsOnDimensions != null || annotationsOnExtendedDimensions != null) {
- annotationsOnAllDimensions = getMergedAnnotationsOnDimensions(returnType.dimensions(), annotationsOnDimensions, extendedDims, annotationsOnExtendedDimensions);
- }
- md.returnType = copyDims(returnType, dims, annotationsOnAllDimensions);
-
+ md.returnType = augmentTypeWithAdditionalDimensions(md.returnType, extendedDims, getAnnotationsOnDimensions(extendedDims), false);
if (this.currentToken == TokenNameLBRACE) {
md.bodyStart = this.endPosition + 1;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
index e596ffcf5..58aa745c1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitProblemFinder.java
@@ -157,7 +157,8 @@ public class CompilationUnitProblemFinder extends Compiler {
compilerOptions.performMethodsFullRecovery = statementsRecovery;
compilerOptions.performStatementsRecovery = statementsRecovery;
compilerOptions.parseLiteralExpressionsAsConstants = !creatingAST; /*parse literal expressions as constants only if not creating a DOM AST*/
- compilerOptions.storeAnnotations = creatingAST; /*store annotations in the bindings if creating a DOM AST*/
+ if (creatingAST)
+ compilerOptions.storeAnnotations = true; /* store annotations in the bindings if creating a DOM AST */
return compilerOptions;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
index 32edad84f..5e9ad1d7c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java
@@ -1,10 +1,13 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 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
- * $Id: HierarchyResolver.java 23404 2010-02-03 14:10:22Z stephan $
+ *
+ * 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
@@ -367,7 +370,7 @@ private void fixSupertypeBindings() {
QualifiedAllocationExpression allocationExpression = localTypeBinding.scope.referenceContext.allocation;
TypeReference type;
if (allocationExpression != null && (type = allocationExpression.type) != null && type.resolvedType != null) {
- localTypeBinding.superclass = (ReferenceBinding) type.resolvedType;
+ localTypeBinding.setSuperClass((ReferenceBinding) type.resolvedType);
continue;
}
}
@@ -382,7 +385,7 @@ private void fixSupertypeBindings() {
if (superclass instanceof ReferenceBinding) {
// ensure we are not creating a cycle (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=215681 )
if (!(subTypeOfType((ReferenceBinding) superclass, typeBinding))) {
- ((SourceTypeBinding) typeBinding).superclass = (ReferenceBinding) superclass;
+ ((SourceTypeBinding) typeBinding).setSuperClass((ReferenceBinding) superclass);
}
}
@@ -406,7 +409,7 @@ private void fixSupertypeBindings() {
}
if (index < length)
System.arraycopy(interfaceBindings, 0, interfaceBindings = new ReferenceBinding[index], 0 , index);
- ((SourceTypeBinding) typeBinding).superInterfaces = interfaceBindings;
+ ((SourceTypeBinding) typeBinding).setSuperInterfaces(interfaceBindings);
}
}
} else if (typeBinding instanceof BinaryTypeBinding) {
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
index c8df6ce81..3ceb39502 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocatorParser.java
@@ -914,16 +914,8 @@ protected void consumeWildcardBoundsSuper() {
}
}
-protected TypeReference copyDims(TypeReference typeRef, int dim) {
- TypeReference result = super.copyDims(typeRef, dim);
- if (this.nodeSet.removePossibleMatch(typeRef) != null)
- this.nodeSet.addPossibleMatch(result);
- else if (this.nodeSet.removeTrustedMatch(typeRef) != null)
- this.nodeSet.addTrustedMatch(result, true);
- return result;
-}
-protected TypeReference copyDims(TypeReference typeRef, int dim, Annotation [][] annotationsOnDimensions) {
- TypeReference result = super.copyDims(typeRef, dim, annotationsOnDimensions);
+protected TypeReference augmentTypeWithAdditionalDimensions(TypeReference typeRef, int additionalDimensions, Annotation [][] additionalAnnotations, boolean isVarargs) {
+ TypeReference result = super.augmentTypeWithAdditionalDimensions(typeRef, additionalDimensions, additionalAnnotations, isVarargs);
if (this.nodeSet.removePossibleMatch(typeRef) != null)
this.nodeSet.addPossibleMatch(result);
else if (this.nodeSet.removeTrustedMatch(typeRef) != null)

Back to the top