merged AspectJ changes and jdt 3f60ba6
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
index 4498f87..faf8ed4 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/CompletionEngine.java
@@ -2494,8 +2494,13 @@
// When completion is inside lambda body, the fake type cannot be attached to the lambda.
ReferenceContext referenceContext = scope.parent.referenceContext();
- CompletionOnAnnotationOfType fakeType = (CompletionOnAnnotationOfType) (referenceContext instanceof CompletionOnAnnotationOfType ? referenceContext : null);
- if (fakeType != null && fakeType.annotations[0] == annot) {
+ CompletionOnAnnotationOfType fakeType;
+ if (referenceContext instanceof CompletionOnAnnotationOfType) {
+ fakeType = (CompletionOnAnnotationOfType) referenceContext;
+ } else {
+ fakeType = new CompletionOnAnnotationOfType(CompletionParser.FAKE_TYPE_NAME, scope.referenceCompilationUnit().compilationResult, annot);
+ }
+ if (fakeType.annotations[0] == annot) {
// When the completion is inside a method body the annotation cannot be accuratly attached to the correct node by completion recovery.
// So 'targetedElement' is not computed in this case.
if (scope.parent.parent == null || !(scope.parent.parent instanceof MethodScope)) {
@@ -2511,8 +2516,7 @@
setSourceAndTokenRange(type.sourceStart, type.sourceEnd);
if (scope.parent.parent != null &&
- !(scope.parent.parent instanceof MethodScope) &&
- fakeType != null && !fakeType.isParameter) {
+ !(scope.parent.parent instanceof MethodScope) && !fakeType.isParameter) {
if (this.completionToken.length <= Keywords.INTERFACE.length
&& CharOperation.prefixEquals(this.completionToken, Keywords.INTERFACE, false /* ignore case */
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnParameterizedQualifiedTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnParameterizedQualifiedTypeReference.java
index 487813c..7a9f66e 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnParameterizedQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnParameterizedQualifiedTypeReference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * Copyright (c) 2004, 2014 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
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.codeassist.complete;
@@ -76,13 +78,13 @@
return this.kind == K_CLASS || this.kind == K_INTERFACE;
}
- public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
- super.resolveType(scope, checkBounds);
+ public TypeBinding resolveType(BlockScope scope, boolean checkBounds, int location) {
+ super.resolveType(scope, checkBounds, location);
throw new CompletionNodeFound(this, this.resolvedType, scope);
}
- public TypeBinding resolveType(ClassScope scope) {
- super.resolveType(scope);
+ public TypeBinding resolveType(ClassScope scope, int location) {
+ super.resolveType(scope, location);
throw new CompletionNodeFound(this, this.resolvedType, 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 7733460..362599d 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
@@ -3409,6 +3409,23 @@
this.restartRecovery = true;
} else {
popElement(K_BETWEEN_ANNOTATION_NAME_AND_RPAREN);
+ if (this.expressionPtr >= 0 && this.expressionStack[this.expressionPtr] instanceof CompletionOnMarkerAnnotationName) {
+ Annotation annotation = (Annotation)this.expressionStack[this.expressionPtr];
+ if(this.currentElement != null) {
+ annotationRecoveryCheckPoint(annotation.sourceStart, annotation.declarationSourceEnd);
+ if (this.currentElement instanceof RecoveredAnnotation) {
+ this.currentElement = ((RecoveredAnnotation)this.currentElement).addAnnotation(annotation, this.identifierPtr);
+ }
+ }
+
+ if(!this.statementRecoveryActivated &&
+ this.options.sourceLevel < ClassFileConstants.JDK1_5 &&
+ this.lastErrorEndPositionBeforeRecovery < this.scanner.currentPosition) {
+ problemReporter().invalidUsageOfAnnotation(annotation);
+ }
+ this.recordStringLiterals = true;
+ return;
+ }
super.consumeNormalAnnotation(isTypeAnnotation);
}
}
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 bbf2021..95313be 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
@@ -479,7 +479,7 @@
if (recoveredBlock != null) {
RecoveredStatement recoveredStatement = recoveredBlock.statementCount > 0 ? recoveredBlock.statements[recoveredBlock.statementCount - 1] : null;
ASTNode parseTree = recoveredStatement != null ? recoveredStatement.updatedStatement(0, new HashSet()) : null;
- if (parseTree == assistNodeParent || parseTree == enclosingNode) {
+ if (parseTree != null && (parseTree == assistNodeParent || parseTree == enclosingNode)) {
recoveredBlock.statements[--recoveredBlock.statementCount] = null;
this.currentElement = recoveredBlock;
}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedQualifiedTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedQualifiedTypeReference.java
index fa26161..ffe9b99 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedQualifiedTypeReference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.codeassist.select;
@@ -29,8 +31,8 @@
this.typeArguments[length] = assistTypeArguments;
}
- public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
- super.resolveType(scope, checkBounds);
+ public TypeBinding resolveType(BlockScope scope, boolean checkBounds, int location) {
+ super.resolveType(scope, checkBounds, location);
//// removed unnecessary code to solve bug 94653
//if(this.resolvedType != null && this.resolvedType.isRawType()) {
// ParameterizedTypeBinding parameterizedTypeBinding = scope.createParameterizedType(((RawTypeBinding)this.resolvedType).type, new TypeBinding[0], this.resolvedType.enclosingType());
@@ -39,8 +41,8 @@
throw new SelectionNodeFound(this.resolvedType);
}
- public TypeBinding resolveType(ClassScope scope) {
- super.resolveType(scope);
+ public TypeBinding resolveType(ClassScope scope, int location) {
+ super.resolveType(scope, location);
//// removed unnecessary code to solve bug 94653
//if(this.resolvedType != null && this.resolvedType.isRawType()) {
// ParameterizedTypeBinding parameterizedTypeBinding = scope.createParameterizedType(((RawTypeBinding)this.resolvedType).type, new TypeBinding[0], this.resolvedType.enclosingType());
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedSingleTypeReference.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedSingleTypeReference.java
index 57f749a..7be0d7a 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedSingleTypeReference.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionOnParameterizedSingleTypeReference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.codeassist.select;
@@ -21,13 +23,13 @@
super(name, typeArguments, 0, pos);
}
- public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
- super.resolveType(scope, checkBounds);
+ public TypeBinding resolveType(BlockScope scope, boolean checkBounds, int location) {
+ super.resolveType(scope, checkBounds, location);
throw new SelectionNodeFound(this.resolvedType);
}
- public TypeBinding resolveType(ClassScope scope) {
- super.resolveType(scope);
+ public TypeBinding resolveType(ClassScope scope, int location) {
+ super.resolveType(scope, location);
throw new SelectionNodeFound(this.resolvedType);
}
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 dcd5aaf..fb824f1 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
@@ -190,6 +190,8 @@
* UnsafeNullnessCast
* ContradictoryNullAnnotationsInferred
* NonNullDefaultDetailIsNotEvaluated
+ * NullNotCompatibleToFreeTypeVariable
+ * NullityMismatchAgainstFreeTypeVariable
* Jesper S Moller - added the following constants
* TargetTypeNotAFunctionalInterface
* OuterLocalMustBeEffectivelyFinal
@@ -1803,7 +1805,11 @@
/** @since 3.10 */
int UnsafeNullnessCast = Internal + 967;
/** @since 3.10 */
- int NonNullDefaultDetailIsNotEvaluated = 968;
+ int NonNullDefaultDetailIsNotEvaluated = 968; // no longer reported
+ /** @since 3.10 */
+ int NullNotCompatibleToFreeTypeVariable = 969;
+ /** @since 3.10 */
+ int NullityMismatchAgainstFreeTypeVariable = 970;
// Java 8 work
/** @since 3.10 */
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 de217d5..7b7eda6 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
@@ -2098,6 +2098,15 @@
startLineIndexes);
}
+ private void completeArgumentAnnotationInfo(Argument[] arguments, List allAnnotationContexts) {
+ for (int i = 0, max = arguments.length; i < max; i++) {
+ Argument argument = arguments[i];
+ if ((argument.bits & ASTNode.HasTypeAnnotations) != 0) {
+ argument.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER, i, allAnnotationContexts);
+ }
+ }
+ }
+
/**
* INTERNAL USE-ONLY
* Complete the creation of a method info by setting up the number of attributes at the right offset.
@@ -2119,12 +2128,7 @@
if ((methodDeclaration.bits & ASTNode.HasTypeAnnotations) != 0) {
Argument[] arguments = methodDeclaration.arguments;
if (arguments != null) {
- for (int i = 0, max = arguments.length; i < max; i++) {
- Argument argument = arguments[i];
- if ((argument.bits & ASTNode.HasTypeAnnotations) != 0) {
- argument.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER, i, allTypeAnnotationContexts);
- }
- }
+ completeArgumentAnnotationInfo(arguments, allTypeAnnotationContexts);
}
Receiver receiver = methodDeclaration.receiver;
if (receiver != null && (receiver.type.bits & ASTNode.HasTypeAnnotations) != 0) {
@@ -2158,6 +2162,12 @@
}
}
}
+ } else if (binding.sourceLambda() != null) { // SyntheticMethodBinding, purpose : LambdaMethod.
+ LambdaExpression lambda = binding.sourceLambda();
+ if ((lambda.bits & ASTNode.HasTypeAnnotations) != 0) {
+ if (lambda.arguments != null)
+ completeArgumentAnnotationInfo(lambda.arguments, allTypeAnnotationContexts);
+ }
}
int size = allTypeAnnotationContexts.size();
if (size != 0) {
@@ -2383,8 +2393,14 @@
if (methodBinding == null) {
this.contentsOffset = startingContentsOffset;
} else {
+ int memberValuePairOffset = this.contentsOffset;
try {
- generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType, startingContentsOffset);
+ generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType, memberValuePairOffset);
+ if (this.contentsOffset == memberValuePairOffset) {
+ // ignore annotation value
+ this.contents[this.contentsOffset++] = 0;
+ this.contents[this.contentsOffset++] = 0;
+ }
} catch(ClassCastException e) {
this.contentsOffset = startingContentsOffset;
} catch(ShouldNotImplement e) {
@@ -3328,6 +3344,11 @@
}
if (this.targetJDK >= ClassFileConstants.JDK1_4) {
AbstractMethodDeclaration methodDeclaration = methodBinding.sourceMethod();
+ if (methodBinding instanceof SyntheticMethodBinding) {
+ SyntheticMethodBinding syntheticMethod = (SyntheticMethodBinding) methodBinding;
+ if (syntheticMethod.purpose == SyntheticMethodBinding.SuperMethodAccess && CharOperation.equals(syntheticMethod.selector, syntheticMethod.targetMethod.selector))
+ methodDeclaration = ((SyntheticMethodBinding)methodBinding).targetMethod.sourceMethod();
+ }
if (methodDeclaration != null) {
Annotation[] annotations = methodDeclaration.annotations;
if (annotations != null) {
@@ -4023,9 +4044,15 @@
}
}
if (targetParameters != Binding.NO_PARAMETERS) {
- for (int i = 0, max = targetParameters.length; i < max; i++) {
- if (methodDeclaration != null && methodDeclaration.arguments != null && methodDeclaration.arguments.length > i && methodDeclaration.arguments[i] != null) {
- Argument argument = methodDeclaration.arguments[i];
+ Argument[] arguments = null;
+ if (methodDeclaration != null && methodDeclaration.arguments != null) {
+ arguments = methodDeclaration.arguments;
+ } else if (binding.sourceLambda() != null) { // SyntheticMethodBinding, purpose : LambdaMethod.
+ arguments = binding.sourceLambda().arguments;
+ }
+ for (int i = 0, max = targetParameters.length, argumentsLength = arguments != null ? arguments.length : 0; i < max; i++) {
+ if (argumentsLength > i && arguments[i] != null) {
+ Argument argument = arguments[i];
length = writeArgumentName(argument.name, argument.binding.modifiers, length);
} else {
length = writeArgumentName(null, ClassFileConstants.AccSynthetic, length);
@@ -5228,6 +5255,9 @@
this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE;
if (this.targetJDK >= ClassFileConstants.JDK1_8) {
this.produceAttributes |= ClassFileConstants.ATTR_TYPE_ANNOTATION;
+ if (options.produceMethodParameters) {
+ this.produceAttributes |= ClassFileConstants.ATTR_METHOD_PARAMETERS;
+ }
}
} else if (this.targetJDK == ClassFileConstants.CLDC_1_1) {
this.targetJDK = ClassFileConstants.JDK1_1; // put back 45.3
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
index 844ddff..4b006cb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -326,7 +326,6 @@
} else {
parsedUnit = this.parser.dietParse(sourceUnit, unitResult);
}
- parsedUnit.bits |= ASTNode.IsImplicitUnit;
// initial type binding creation
this.lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction);
addCompilationUnit(sourceUnit, parsedUnit);
@@ -827,14 +826,23 @@
int index = 0;
for (int i = bottom; i < top; i++) {
CompilationUnitDeclaration currentUnit = this.unitsToProcess[i];
- if ((currentUnit.bits & ASTNode.IsImplicitUnit) == 0) {
- currentUnits[index++] = currentUnit;
- }
+ currentUnits[index++] = currentUnit;
}
if (index != length) {
System.arraycopy(currentUnits, 0, (currentUnits = new CompilationUnitDeclaration[index]), 0, index);
}
this.annotationProcessorManager.processAnnotations(currentUnits, binaryTypeBindingsTemp, false);
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=407841
+ // It is possible that during the #processAnnotations() call, some units in the next batch would have been
+ // brought forward and compiled already. If there are any such, process them for annotations then and there.
+ // This would avoid the complications of marking some units as compiled but not-annotation-processed-yet.
+ if (top < this.totalUnits) {
+ length = this.totalUnits - top; // NOTE: Reuse the same variable, but make sure it's not used after this point
+ CompilationUnitDeclaration[] addedUnits = new CompilationUnitDeclaration[length];
+ System.arraycopy(this.unitsToProcess, top, addedUnits, 0, length);
+ this.annotationProcessorManager.processAnnotations(addedUnits, binaryTypeBindingsTemp, false);
+ this.annotationProcessorStartIndex = top;
+ }
ICompilationUnit[] newUnits = this.annotationProcessorManager.getNewUnits();
newUnitSize = newUnits.length;
ReferenceBinding[] newClassFiles = this.annotationProcessorManager.getNewClassFiles();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
index 6d10931..33aae2b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
@@ -11,6 +11,7 @@
* bug 319201 - [null] no warning when unboxing SingleNameReference causes NPE
* bug 403086 - [compiler][null] include the effect of 'assert' in syntactic null analysis for fields
* bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking
+ * Bug 422796 - [compiler][null] boxed boolean reported as potentially null after null test in lazy disjunction
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -69,7 +70,7 @@
if ((flowContext.tagBits & FlowContext.INSIDE_NEGATION) != 0)
flowContext.expireNullCheckedFieldInfo();
this.left.checkNPEbyUnboxing(currentScope, flowContext, flowInfo);
- this.right.checkNPEbyUnboxing(currentScope, flowContext, flowInfo);
+ this.right.checkNPEbyUnboxing(currentScope, flowContext, leftInfo.initsWhenTrue());
FlowInfo mergedInfo = FlowInfo.conditional(
rightInfo.safeInitsWhenTrue(),
leftInfo.initsWhenFalse().unconditionalInits().mergedWith(
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 5891f7c..2daf398 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
@@ -28,6 +28,7 @@
* Bug 427483 - [Java 8] Variables in lambdas sometimes can't be resolved
* Bug 428352 - [1.8][compiler] Resolution errors don't always surface
* Bug 427163 - [1.8][null] bogus error "Contradictory null specification" on varags
+ * Bug 432348 - [1.8] Internal compiler error (NPE) after upgrade to 1.8
* 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
@@ -977,7 +978,7 @@
}
}
if (copySE8AnnotationsToType)
- copySE8AnnotationsToType(scope, recipient, sourceAnnotations);
+ copySE8AnnotationsToType(scope, recipient, sourceAnnotations, true);
return annotations;
}
@@ -1003,7 +1004,7 @@
}
// When SE8 annotations feature in SE7 locations, they get attributed to the declared entity. Copy/move these to the type of the declared entity (field, local, argument etc.)
- public static void copySE8AnnotationsToType(BlockScope scope, Binding recipient, Annotation[] annotations) {
+ public static void copySE8AnnotationsToType(BlockScope scope, Binding recipient, Annotation[] annotations, boolean isLegalLocation) {
if (annotations == null || annotations.length == 0 || recipient == null)
return;
@@ -1027,12 +1028,15 @@
int se8count = 0;
long se8nullBits = 0;
Annotation se8NullAnnotation = null;
+ int firstSE8 = -1, lastSE8 = 0;
for (int i = 0, length = annotations.length; i < length; i++) {
AnnotationBinding annotation = annotations[i].getCompilerAnnotation();
if (annotation == null) continue;
final ReferenceBinding annotationType = annotation.getAnnotationType();
long metaTagBits = annotationType.getAnnotationTagBits();
if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) {
+ if (firstSE8 == -1) firstSE8 = i;
+ lastSE8 = i;
if (se8Annotations == null) {
se8Annotations = new AnnotationBinding[] { annotation };
se8count = 1;
@@ -1050,6 +1054,10 @@
}
}
if (se8Annotations != null) {
+ if (!isLegalLocation) {
+ scope.problemReporter().misplacedTypeAnnotations(annotations[firstSE8], annotations[lastSE8]);
+ return;
+ }
switch (recipient.kind()) {
case Binding.LOCAL:
LocalVariableBinding local = (LocalVariableBinding) recipient;
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 5fd41cf..ec66cc1 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
@@ -36,6 +36,7 @@
* Bug 428352 - [1.8][compiler] Resolution errors don't always surface
* Bug 429203 - [1.8][compiler] NPE in AllocationExpression.binding
* Bug 429430 - [1.8] Lambdas and method reference infer wrong exception type with generics (RuntimeException instead of IOException)
+ * Bug 434297 - [1.8] NPE in LamdaExpression.analyseCode with lamda expression nested in a conditional expression
* 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
@@ -619,6 +620,7 @@
if ((scope.problemReporter().computeSeverity(IProblem.RedundantSpecificationOfTypeArguments) == ProblemSeverities.Ignore) || scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_7) return;
if (allocationType.arguments == null) return; // raw binding
if (this.genericTypeArguments != null) return; // diamond can't occur with explicit type args for constructor
+ if (this.type == null) return;
if (argumentTypes == Binding.NO_PARAMETERS && this.typeExpected instanceof ParameterizedTypeBinding) {
ParameterizedTypeBinding expected = (ParameterizedTypeBinding) this.typeExpected;
if (expected.arguments != null && allocationType.arguments.length == expected.arguments.length) {
@@ -741,11 +743,21 @@
return this.binding;
}
public TypeBinding checkAgainstFinalTargetType(TypeBinding targetType, Scope scope) {
+ // confer MessageSend.checkAgainstFinalTargetType(,,):
+ if (this.binding instanceof ParameterizedGenericMethodBinding) {
+ InferenceContext18 ctx = getInferenceContext((ParameterizedMethodBinding) this.binding);
+ if (ctx != null && ctx.stepCompleted < InferenceContext18.TYPE_INFERRED) {
+ this.typeExpected = targetType;
+ MethodBinding updatedBinding = ctx.inferInvocationType(this, (ParameterizedGenericMethodBinding) this.binding);
+ if (updateBindings(updatedBinding, targetType)) {
+ ASTNode.resolvePolyExpressionArguments(this, updatedBinding, scope);
+ }
+ }
+ }
if (this.suspendedResolutionState != null) {
return resolvePart3(this.suspendedResolutionState);
- // also: should this trigger any propagation to inners, too?
}
- return super.checkAgainstFinalTargetType(targetType, scope);
+ return this.resolvedType;
}
public Expression[] arguments() {
return this.arguments;
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 6b0b4a9..674f747 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
@@ -18,6 +18,7 @@
* Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Bug 424728 - [1.8][null] Unexpected error: The nullness annotation 'XXXX' is not applicable at this location
* Bug 392245 - [1.8][compiler][null] Define whether / how @NonNullByDefault applies to TYPE_USE locations
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
* 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
@@ -36,6 +37,7 @@
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.EnumConstantSignature;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.impl.IrritantSet;
@@ -304,7 +306,8 @@
}
/**
- * Compute the bit pattern for recognized standard annotations the compiler may need to act upon
+ * Compute the bit pattern for recognized standard annotations the compiler may need to act upon.
+ * The lower bits (Binding.NullnessDefaultMASK) do not belong in tagBits, but in defaultNullness.
*/
private long detectStandardAnnotation(Scope scope, ReferenceBinding annotationType, MemberValuePair valueAttribute) {
long tagBits = 0;
@@ -390,28 +393,98 @@
tagBits |= TagBits.AnnotationNonNull;
break;
case TypeIds.T_ConfiguredAnnotationNonNullByDefault :
+ // seeing this id implies that null annotation analysis is enabled
+ Object value = null;
if (valueAttribute != null) {
if (valueAttribute.value instanceof FalseLiteral) {
// parameter 'false' means: this annotation cancels any defaults
tagBits |= TagBits.AnnotationNullUnspecifiedByDefault;
break;
} else if (valueAttribute.compilerElementPair != null) {
- Object value = valueAttribute.compilerElementPair.value;
- if (value instanceof Object[] && ((Object[])value).length == 0) {
- // empty parameter means: this annotation cancels any defaults
- tagBits |= TagBits.AnnotationNullUnspecifiedByDefault;
- break;
- } else {
- scope.problemReporter().nonNullDefaultDetailNotEvaluated(valueAttribute);
- }
+ value = valueAttribute.compilerElementPair.value;
+ }
+ } else if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8) { // fetch default value - TODO: cache it?
+ MethodBinding[] methods = annotationType.methods();
+ if (methods != null && methods.length == 1) {
+ Object defaultValue = methods[0].getDefaultValue();
+ if (defaultValue instanceof Object[])
+ value = defaultValue;
}
}
- tagBits |= TagBits.AnnotationNonNullByDefault;
+ if (value != null) {
+ tagBits |= nullTagBitsFromAnnotationValue(value);
+ } else {
+ // neither explicit value, nor default value from DefaultLocation (1.8)
+ tagBits |= TagBits.AnnotationNonNullByDefault;
+ }
break;
}
return tagBits;
}
+ /**
+ * Convert the value() attribute of @NonNullByDefault into a bitvector a la {@link Binding#NullnessDefaultMASK}.
+ * This method understands value encodings from source and binary types.
+ *
+ * <b>pre:</b> null annotation analysis is enabled
+ */
+ public static int nullTagBitsFromAnnotationValue(Object value) {
+ if (value instanceof Object[]) {
+ if (((Object[]) value).length == 0) {
+ return Binding.NULL_UNSPECIFIED_BY_DEFAULT;
+ } else {
+ int bits = 0;
+ for (Object single : (Object[])value)
+ bits |= evaluateDefaultNullnessLocation(single);
+ return bits;
+ }
+ } else {
+ return evaluateDefaultNullnessLocation(value);
+ }
+ }
+
+ private static int evaluateDefaultNullnessLocation(Object value) {
+ char[] name = null;
+ if (value instanceof FieldBinding) {
+ name = ((FieldBinding) value).name;
+ } else if (value instanceof EnumConstantSignature) {
+ name = ((EnumConstantSignature) value).getEnumConstantName();
+ } else if (value instanceof ElementValuePair.UnresolvedEnumConstant) {
+ name = ((ElementValuePair.UnresolvedEnumConstant) value).getEnumConstantName();
+ }
+ if (name != null) {
+ switch (name.length) {
+ case 5:
+ if (CharOperation.equals(name, TypeConstants.DEFAULT_LOCATION__FIELD))
+ return Binding.DefaultLocationField;
+ break;
+ case 9:
+ if (CharOperation.equals(name, TypeConstants.DEFAULT_LOCATION__PARAMETER))
+ return Binding.DefaultLocationParameter;
+ break;
+ case 10:
+ if (CharOperation.equals(name, TypeConstants.DEFAULT_LOCATION__TYPE_BOUND))
+ return Binding.DefaultLocationTypeBound;
+ break;
+ case 11:
+ if (CharOperation.equals(name, TypeConstants.DEFAULT_LOCATION__RETURN_TYPE))
+ return Binding.DefaultLocationReturnType;
+ break;
+ case 13 :
+ if (CharOperation.equals(name, TypeConstants.DEFAULT_LOCATION__TYPE_ARGUMENT))
+ return Binding.DefaultLocationTypeArgument;
+ break;
+ case 14 :
+ if (CharOperation.equals(name, TypeConstants.DEFAULT_LOCATION__TYPE_PARAMETER))
+ return Binding.DefaultLocationTypeParameter;
+ if (CharOperation.equals(name, TypeConstants.DEFAULT_LOCATION__ARRAY_CONTENTS))
+ return Binding.DefaultLocationArrayContents;
+ break;
+ }
+ }
+ return 0;
+ }
+
static String getRetentionName(long tagBits) {
if ((tagBits & TagBits.AnnotationRuntimeRetention) == TagBits.AnnotationRuntimeRetention) {
// TagBits.AnnotationRuntimeRetention combines both TagBits.AnnotationClassRetention & TagBits.AnnotationSourceRetention
@@ -518,6 +591,12 @@
StringBuffer targetBuffer = new StringBuffer();
void check(long targetMask, char[] targetName) {
if ((containerAnnotationTypeTargets & targetMask & ~targets) != 0) {
+ // if targetMask equals TagBits.AnnotationForType implies
+ // TagBits.AnnotationForType is part of containerAnnotationTypeTargets
+ if (targetMask == TagBits.AnnotationForType &&
+ (targets & TagBits.AnnotationForTypeUse) != 0) {
+ return;
+ }
add(targetName);
}
}
@@ -793,12 +872,14 @@
this.compilerAnnotation = scope.environment().createAnnotation((ReferenceBinding) this.resolvedType, computeElementValuePairs());
// recognize standard annotations ?
long tagBits = detectStandardAnnotation(scope, annotationType, valueAttribute);
+ int defaultNullness = (int)(tagBits & Binding.NullnessDefaultMASK);
+ tagBits &= ~Binding.NullnessDefaultMASK;
// record annotation positions in the compilation result
scope.referenceCompilationUnit().recordSuppressWarnings(IrritantSet.NLS, null, this.sourceStart, this.declarationSourceEnd);
if (this.recipient != null) {
int kind = this.recipient.kind();
- if (tagBits != 0) {
+ if (tagBits != 0 || defaultNullness != 0) {
// tag bits onto recipient
switch (kind) {
case Binding.PACKAGE :
@@ -819,6 +900,7 @@
}
recordSuppressWarnings(scope, start, typeDeclaration.declarationSourceEnd, scope.compilerOptions().suppressWarnings);
}
+ sourceType.defaultNullness |= defaultNullness;
break;
case Binding.METHOD :
MethodBinding sourceMethod = (MethodBinding) this.recipient;
@@ -839,6 +921,7 @@
// for declaration annotations the inapplicability will be reported below
sourceMethod.tagBits &= ~TagBits.AnnotationNullMASK;
}
+ sourceMethod.defaultNullness |= defaultNullness;
break;
case Binding.FIELD :
FieldBinding sourceField = (FieldBinding) this.recipient;
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 440d41c..8176963 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
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -101,8 +103,8 @@
}
}
- protected TypeBinding internalResolveType(Scope scope) {
- TypeBinding internalResolveType = super.internalResolveType(scope);
+ protected TypeBinding internalResolveType(Scope scope, int location) {
+ TypeBinding internalResolveType = super.internalResolveType(scope, location);
return internalResolveType;
}
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 0b32ffd..0513625 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
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -173,8 +175,8 @@
visitor.endVisit(this, scope);
}
- protected TypeBinding internalResolveType(Scope scope) {
- TypeBinding internalResolveType = super.internalResolveType(scope);
+ protected TypeBinding internalResolveType(Scope scope, int location) {
+ TypeBinding internalResolveType = super.internalResolveType(scope, location);
return internalResolveType;
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
index b603b9e..171ef8d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
@@ -20,6 +20,7 @@
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
* Bug 400874 - [1.8][compiler] Inference infrastructure should evolve to meet JLS8 18.x (Part G of JSR335 spec)
* Bug 427438 - [1.8][compiler] NPE at org.eclipse.jdt.internal.compiler.ast.ConditionalExpression.generateCode(ConditionalExpression.java:280)
+ * Bug 430150 - [1.8][null] stricter checking against type variables
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 415541 - [1.8][compiler] Type annotations in the body of static initializer get dropped
*******************************************************************************/
@@ -549,7 +550,8 @@
if (castType != null) {
if (expressionType != null) {
- boolean nullAnnotationMismatch = NullAnnotationMatching.analyse(castType, expressionType, -1).isAnyMismatch();
+ boolean nullAnnotationMismatch = scope.compilerOptions().isAnnotationBasedNullAnalysisEnabled
+ && NullAnnotationMatching.analyse(castType, expressionType, -1).isAnyMismatch();
boolean isLegal = checkCastTypesCompatibility(scope, castType, expressionType, this.expression);
if (isLegal) {
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 b69b9aa..ee31086 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
@@ -464,6 +464,12 @@
if (this.valueIfFalse instanceof CastExpression) this.valueIfFalse.bits |= DisableUnnecessaryCastCheck; // will check later on
this.originalValueIfFalseType = this.valueIfFalse.resolveType(scope);
+ if (isPolyExpression()) {
+ if (this.expectedType == null) {
+ this.polyExpressionScope = scope; // preserve for eventual resolution/error reporting.
+ }
+ }
+
if (conditionType == null || this.originalValueIfTrueType == null || this.originalValueIfFalseType == null)
return null;
} else {
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 f313250..918b1b4 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
@@ -378,8 +378,10 @@
if (match != null) {
return checkUnsafeCast(scope, castType, expressionType, match, false);
}
+ TypeBinding bound = ((WildcardBinding)expressionType).bound;
+ if (bound == null) bound = scope.getJavaLangObject();
// recursively on the type variable upper bound
- return checkCastTypesCompatibility(scope, castType, ((WildcardBinding)expressionType).bound, expression);
+ return checkCastTypesCompatibility(scope, castType, bound, expression);
case Binding.INTERSECTION_CAST_TYPE:
ReferenceBinding [] intersectingTypes = expressionType.getIntersectingTypes();
for (int i = 0, length = intersectingTypes.length; i < length; i++) {
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 06e0996..fc61e17 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
@@ -319,7 +319,8 @@
!MethodVerifier.areReturnTypesCompatible(this.method, inheritedMethod, this.environment))
continue;
final MethodBinding originalInherited = inheritedMethod.original();
- if (!this.method.areParameterErasuresEqual(originalInherited) || TypeBinding.notEquals(this.method.returnType.erasure(), originalInherited.returnType.erasure()))
+ final MethodBinding originalOverride = this.method.original();
+ if (!originalOverride.areParameterErasuresEqual(originalInherited) || TypeBinding.notEquals(originalOverride.returnType.erasure(), originalInherited.returnType.erasure()))
add(originalInherited);
}
collectBridges(superInterface.superInterfaces());
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 8782b5a..3ae7952 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
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator
*******************************************************************************/
@@ -66,7 +68,7 @@
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
*/
- public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
+ public TypeBinding resolveType(BlockScope scope, boolean checkBounds, int location) {
int length = this.typeReferences.length;
ReferenceBinding[] intersectingTypes = new ReferenceBinding[length];
@@ -76,7 +78,7 @@
nextType:
for (int i = 0; i < length; i++) {
final TypeReference typeReference = this.typeReferences[i];
- TypeBinding type = typeReference.resolveType(scope, checkBounds);
+ TypeBinding type = typeReference.resolveType(scope, checkBounds, location);
if (type == null || ((type.tagBits & TagBits.HasMissingType) != 0)) {
hasError = true;
continue;
@@ -196,4 +198,4 @@
}
return output;
}
-}
\ No newline at end of file
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
index fded012..251a7a2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for
* Bug 400874 - [1.8][compiler] Inference infrastructure should evolve to meet JLS8 18.x (Part G of JSR335 spec)
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -610,7 +611,7 @@
// Scan all @param tags
for (int i = 0; i < paramTypeParamLength; i++) {
JavadocSingleTypeReference param = this.paramTypeParameters[i];
- TypeBinding paramBindind = param.internalResolveType(scope);
+ TypeBinding paramBindind = param.internalResolveType(scope, 0);
if (paramBindind != null && paramBindind.isValidBinding()) {
if (paramBindind.isTypeVariable()) {
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=397888
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 64c9547..c18dd29 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -59,7 +61,7 @@
* Resolves type on a Block, Class or CompilationUnit scope.
* We need to modify resoling behavior to avoid raw type creation.
*/
- protected TypeBinding internalResolveType(Scope scope) {
+ protected TypeBinding internalResolveType(Scope scope, int location) {
// handle the error here
this.constant = Constant.NotAConstant;
if (this.resolvedType != null) { // is a shared type reference which was already resolved
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java
index ee7df88..431ea1e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocQualifiedTypeReference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -74,11 +76,11 @@
protected void reportInvalidType(Scope scope) {
scope.problemReporter().javadocInvalidType(this, this.resolvedType, scope.getDeclarationModifiers());
}
- public TypeBinding resolveType(BlockScope blockScope, boolean checkBounds) {
+ public TypeBinding resolveType(BlockScope blockScope, boolean checkBounds, int location) {
return internalResolveType(blockScope, checkBounds);
}
- public TypeBinding resolveType(ClassScope classScope) {
+ public TypeBinding resolveType(ClassScope classScope, int location) {
return internalResolveType(classScope, false);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java
index 19aed08..1c66784 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/JavadocSingleTypeReference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -36,7 +38,7 @@
/*
* We need to modify resolving behavior to handle package references
*/
- protected TypeBinding internalResolveType(Scope scope) {
+ protected TypeBinding internalResolveType(Scope scope, int location) {
// handle the error here
this.constant = Constant.NotAConstant;
if (this.resolvedType != null) { // is a shared type reference which was already resolved
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 f669111..99407fd 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
@@ -30,6 +30,7 @@
* Bug 428786 - [1.8][compiler] Inference needs to compute the "ground target type" when reducing a lambda compatibility constraint
* Bug 428980 - [1.8][null] simple expression as lambda body doesn't leverage null annotation on argument
* Bug 429430 - [1.8] Lambdas and method reference infer wrong exception type with generics (RuntimeException instead of IOException)
+ * Bug 432110 - [1.8][compiler] nested lambda type incorrectly inferred vs javac
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas
*******************************************************************************/
@@ -602,6 +603,10 @@
}
public StringBuffer printExpression(int tab, StringBuffer output) {
+ return printExpression(tab, output, false);
+ }
+
+ public StringBuffer printExpression(int tab, StringBuffer output, boolean makeShort) {
int parenthesesCount = (this.bits & ASTNode.ParenthesizedMASK) >> ASTNode.ParenthesizedSHIFT;
String suffix = ""; //$NON-NLS-1$
for(int i = 0; i < parenthesesCount; i++) {
@@ -616,10 +621,14 @@
}
}
output.append(") -> " ); //$NON-NLS-1$
- if (this.body != null)
- this.body.print(this.body instanceof Block ? tab : 0, output);
- else
- output.append("<@incubator>"); //$NON-NLS-1$
+ if (makeShort) {
+ output.append("{}"); //$NON-NLS-1$
+ } else {
+ if (this.body != null)
+ this.body.print(this.body instanceof Block ? tab : 0, output);
+ else
+ output.append("<@incubator>"); //$NON-NLS-1$
+ }
return output.append(suffix);
}
@@ -836,6 +845,8 @@
if (this.body instanceof Block) {
if (copy.returnsVoid) {
copy.shapeAnalysisComplete = true;
+ } else {
+ copy.valueCompatible = this.returnsValue;
}
} else {
copy.voidCompatible = ((Expression) this.body).statementExpression();
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 d041dec..12d369b 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
@@ -24,6 +24,7 @@
* Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
* Bug 427438 - [1.8][compiler] NPE at org.eclipse.jdt.internal.compiler.ast.ConditionalExpression.generateCode(ConditionalExpression.java:280)
+ * Bug 430150 - [1.8][null] stricter checking against type variables
* 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
@@ -98,7 +99,9 @@
this.bits &= ~FirstAssignmentToLocal; // int i = (i = 0);
}
flowInfo.markAsDefinitelyAssigned(this.binding);
- nullStatus = NullAnnotationMatching.checkAssignment(currentScope, flowContext, this.binding, nullStatus, this.initialization, this.initialization.resolvedType);
+ if (currentScope.compilerOptions().isAnnotationBasedNullAnalysisEnabled) {
+ nullStatus = NullAnnotationMatching.checkAssignment(currentScope, flowContext, this.binding, nullStatus, this.initialization, this.initialization.resolvedType);
+ }
if ((this.binding.type.tagBits & TagBits.IsBaseType) == 0) {
flowInfo.markNullStatus(this.binding, nullStatus);
// no need to inform enclosing try block since its locals won't get
@@ -219,7 +222,7 @@
Binding existingVariable = scope.getBinding(this.name, Binding.VARIABLE, this, false /*do not resolve hidden field*/);
if (existingVariable != null && existingVariable.isValidBinding()){
boolean localExists = existingVariable instanceof LocalVariableBinding;
- if (localExists && (this.bits & ASTNode.ShadowsOuterLocal) != 0 && scope.isLambdaSubscope()) {
+ if (localExists && (this.bits & ASTNode.ShadowsOuterLocal) != 0 && scope.isLambdaSubscope() && this.hiddenVariableDepth == 0) {
scope.problemReporter().lambdaRedeclaresLocal(this);
} else if (localExists && this.hiddenVariableDepth == 0) {
scope.problemReporter().redefineLocal(this);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java
index 103812b..81ca5c8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MemberValuePair.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -10,6 +10,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 434570 - Generic type mismatch for parametrized class annotation attribute with inner class
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -58,7 +59,7 @@
return output;
}
- public void resolveTypeExpecting(BlockScope scope, TypeBinding requiredType) {
+ public void resolveTypeExpecting(final BlockScope scope, final TypeBinding requiredType) {
if (this.value == null) {
this.compilerElementPair = new ElementValuePair(this.name, this.value, this.binding);
@@ -76,7 +77,7 @@
}
this.value.setExpectedType(requiredType); // needed in case of generic method invocation - looks suspect, generic method invocation here ???
- TypeBinding valueType;
+ final TypeBinding valueType;
if (this.value instanceof ArrayInitializer) {
ArrayInitializer initializer = (ArrayInitializer) this.value;
valueType = initializer.resolveTypeExpecting(scope, this.binding.returnType);
@@ -101,25 +102,38 @@
if (valueType == null)
return;
- TypeBinding leafType = requiredType.leafComponentType();
- if (!(this.value.isConstantValueOfTypeAssignableToType(valueType, requiredType)
- || valueType.isCompatibleWith(requiredType))) {
-
- if (!(requiredType.isArrayType()
- && requiredType.dimensions() == 1
- && (this.value.isConstantValueOfTypeAssignableToType(valueType, leafType)
- || valueType.isCompatibleWith(leafType)))) {
-
- if (leafType.isAnnotationType() && !valueType.isAnnotationType()) {
- scope.problemReporter().annotationValueMustBeAnnotation(this.binding.declaringClass, this.name, this.value, leafType);
+ final TypeBinding leafType = requiredType.leafComponentType();
+ // the next check may need deferring:
+ final boolean[] shouldExit = new boolean[1];
+ Runnable check = new Runnable() {
+ @Override
+ public void run() {
+ if (!(MemberValuePair.this.value.isConstantValueOfTypeAssignableToType(valueType, requiredType)
+ || valueType.isCompatibleWith(requiredType))) {
+ if (!(requiredType.isArrayType()
+ && requiredType.dimensions() == 1
+ && (MemberValuePair.this.value.isConstantValueOfTypeAssignableToType(valueType, leafType)
+ || valueType.isCompatibleWith(leafType)))) {
+
+ if (leafType.isAnnotationType() && !valueType.isAnnotationType()) {
+ scope.problemReporter().annotationValueMustBeAnnotation(MemberValuePair.this.binding.declaringClass,
+ MemberValuePair.this.name, MemberValuePair.this.value, leafType);
+ } else {
+ scope.problemReporter().typeMismatchError(valueType, requiredType, MemberValuePair.this.value, null);
+ }
+ shouldExit[0] = true; // TODO may allow to proceed to find more errors at once
+ }
} else {
- scope.problemReporter().typeMismatchError(valueType, requiredType, this.value, null);
+ scope.compilationUnitScope().recordTypeConversion(requiredType.leafComponentType(), valueType.leafComponentType());
+ MemberValuePair.this.value.computeConversion(scope, requiredType, valueType);
}
- return; // may allow to proceed to find more errors at once
}
- } else {
- scope.compilationUnitScope().recordTypeConversion(requiredType.leafComponentType(), valueType.leafComponentType());
- this.value.computeConversion(scope, requiredType, valueType);
+ };
+ // ... now or later?
+ if (!scope.deferCheck(check)) {
+ check.run();
+ if (shouldExit[0])
+ return;
}
// annotation methods can only return base types, String, Class, enum type, annotation types and arrays of these
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 db03223..b7c9cd5 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
@@ -15,6 +15,7 @@
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.CaptureBinding;
import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
@@ -40,19 +41,22 @@
*/
public class NullAnnotationMatching {
- public static final NullAnnotationMatching NULL_ANNOTATIONS_OK = new NullAnnotationMatching(0, null);
- public static final NullAnnotationMatching NULL_ANNOTATIONS_UNCHECKED = new NullAnnotationMatching(1, null);
- public static final NullAnnotationMatching NULL_ANNOTATIONS_MISMATCH = new NullAnnotationMatching(2, null);
+ public static final NullAnnotationMatching NULL_ANNOTATIONS_OK = new NullAnnotationMatching(0, FlowInfo.UNKNOWN, null);
+ public static final NullAnnotationMatching NULL_ANNOTATIONS_OK_NONNULL = new NullAnnotationMatching(0, FlowInfo.NON_NULL, null);
+ public static final NullAnnotationMatching NULL_ANNOTATIONS_UNCHECKED = new NullAnnotationMatching(1, FlowInfo.UNKNOWN, null);
+ public static final NullAnnotationMatching NULL_ANNOTATIONS_MISMATCH = new NullAnnotationMatching(2, FlowInfo.UNKNOWN, null);
/** 0 = OK, 1 = unchecked, 2 = definite mismatch */
public final int severity;
/** If non-null this field holds the supertype of the provided type which was used for direct matching. */
public final TypeBinding superTypeHint;
+ public final int nullStatus;
- public NullAnnotationMatching(int severity, TypeBinding superTypeHint) {
+ public NullAnnotationMatching(int severity, int nullStatus, TypeBinding superTypeHint) {
this.severity = severity;
this.superTypeHint = superTypeHint;
+ this.nullStatus = nullStatus;
}
public boolean isAnyMismatch() { return this.severity != 0; }
@@ -89,6 +93,8 @@
} else if (annotationStatus.isUnchecked()) {
flowContext.recordNullityMismatch(currentScope, expression, providedType, var.type, nullStatus);
hasReported = true;
+ } else if (annotationStatus.nullStatus != FlowInfo.UNKNOWN) {
+ return annotationStatus.nullStatus;
}
}
if (lhsTagBits == TagBits.AnnotationNonNull && nullStatus != FlowInfo.NON_NULL) {
@@ -109,12 +115,24 @@
* @return a status object representing the severity of mismatching plus optionally a supertype hint
*/
public static NullAnnotationMatching analyse(TypeBinding requiredType, TypeBinding providedType, int nullStatus) {
- return analyse(requiredType, providedType, nullStatus, false);
+ return analyse(requiredType, providedType, null, nullStatus, false);
}
- // additional parameter strict: if true we do not tolerate incompatibly missing annotations on type parameters (for overriding analysis)
- public static NullAnnotationMatching analyse(TypeBinding requiredType, TypeBinding providedType, int nullStatus, boolean strict) {
+ /**
+ * Find any mismatches between the two given types, which are caused by null type annotations.
+ * @param requiredType
+ * @param providedType
+ * @param providedSubstitute in inheritance situations this maps the providedType into the realm of the subclass, needed for TVB identity checks.
+ * Pass null if not interested in these added checks.
+ * @param nullStatus we are only interested in NULL or NON_NULL, -1 indicates that we are in a recursion, where flow info is ignored
+ * @param strict if true we do not tolerate incompatibly missing annotations on type parameters (for overriding analysis)
+ * @return a status object representing the severity of mismatching plus optionally a supertype hint
+ */
+ public static NullAnnotationMatching analyse(TypeBinding requiredType, TypeBinding providedType, TypeBinding providedSubstitute, int nullStatus, boolean strict) {
int severity = 0;
TypeBinding superTypeHint = null;
+ NullAnnotationMatching okStatus = NullAnnotationMatching.NULL_ANNOTATIONS_OK;
+ if (areSameTypes(requiredType, providedType, providedSubstitute)) // for type variable identity (and as shortcut for others)
+ return okStatus;
if (requiredType instanceof ArrayBinding) {
long[] requiredDimsTagBits = ((ArrayBinding)requiredType).nullTagBitsPerDimension;
if (requiredDimsTagBits != null) {
@@ -139,13 +157,15 @@
return NullAnnotationMatching.NULL_ANNOTATIONS_MISMATCH;
}
}
- } else if (requiredType.hasNullTypeAnnotations() || providedType.hasNullTypeAnnotations()) {
+ } else if (requiredType.hasNullTypeAnnotations() || providedType.hasNullTypeAnnotations() || requiredType.isTypeVariable()) {
long requiredBits = requiredNullTagBits(requiredType);
if (requiredBits != TagBits.AnnotationNullable // nullable lhs accepts everything, ...
|| nullStatus == -1) // only at detail/recursion even nullable must be matched exactly
{
long providedBits = providedNullTagBits(providedType);
severity = computeNullProblemSeverity(requiredBits, providedBits, nullStatus, strict && nullStatus == -1);
+ if (severity == 0 && (providedBits & TagBits.AnnotationNonNull) != 0)
+ okStatus = NullAnnotationMatching.NULL_ANNOTATIONS_OK_NONNULL;
}
if (severity < 2) {
TypeBinding providedSuper = providedType.findSuperTypeOriginatingFrom(requiredType);
@@ -154,26 +174,49 @@
if (requiredType.isParameterizedType() && providedSuper instanceof ParameterizedTypeBinding) { // TODO(stephan): handle providedType.isRaw()
TypeBinding[] requiredArguments = ((ParameterizedTypeBinding) requiredType).arguments;
TypeBinding[] providedArguments = ((ParameterizedTypeBinding) providedSuper).arguments;
+ TypeBinding[] providedSubstitutes = (providedSubstitute instanceof ParameterizedTypeBinding) ? ((ParameterizedTypeBinding)providedSubstitute).arguments : null;
if (requiredArguments != null && providedArguments != null && requiredArguments.length == providedArguments.length) {
for (int i = 0; i < requiredArguments.length; i++) {
- NullAnnotationMatching status = analyse(requiredArguments[i], providedArguments[i], -1, strict);
+ TypeBinding providedArgSubstitute = providedSubstitutes != null ? providedSubstitutes[i] : null;
+ NullAnnotationMatching status = analyse(requiredArguments[i], providedArguments[i], providedArgSubstitute, -1, strict);
severity = Math.max(severity, status.severity);
if (severity == 2)
- return new NullAnnotationMatching(severity, superTypeHint);
+ return new NullAnnotationMatching(severity, nullStatus, superTypeHint);
}
}
}
TypeBinding requiredEnclosing = requiredType.enclosingType();
TypeBinding providedEnclosing = providedType.enclosingType();
if (requiredEnclosing != null && providedEnclosing != null) {
- NullAnnotationMatching status = analyse(requiredEnclosing, providedEnclosing, -1, strict);
+ TypeBinding providedEnclSubstitute = providedSubstitute != null ? providedSubstitute.enclosingType() : null;
+ NullAnnotationMatching status = analyse(requiredEnclosing, providedEnclosing, providedEnclSubstitute, -1, strict);
severity = Math.max(severity, status.severity);
}
}
}
if (severity == 0)
- return NullAnnotationMatching.NULL_ANNOTATIONS_OK;
- return new NullAnnotationMatching(severity, superTypeHint);
+ return okStatus;
+ return new NullAnnotationMatching(severity, nullStatus, superTypeHint);
+ }
+
+ /** Are both types identical wrt the unannotated type and any null type annotations? Only unstructured types are considered. */
+ protected static boolean areSameTypes(TypeBinding requiredType, TypeBinding providedType, TypeBinding providedSubstitute) {
+ if (requiredType == providedType) //$IDENTITY-COMPARISON$ // short cut for really-really-same types
+ return true;
+ if (requiredType.isParameterizedType() || requiredType.isArrayType())
+ return false; // not analysing details here
+ if (TypeBinding.notEquals(requiredType, providedType)) {
+ if (requiredType instanceof CaptureBinding) {
+ // when providing the lower bound of the required type where definitely fine:
+ TypeBinding lowerBound = ((CaptureBinding)requiredType).lowerBound;
+ if (lowerBound != null && areSameTypes(lowerBound, providedType, providedSubstitute))
+ return true;
+ } else if (requiredType.kind() == Binding.TYPE_PARAMETER && requiredType == providedSubstitute) { //$IDENTITY-COMPARISON$
+ return true;
+ }
+ return false;
+ }
+ return (requiredType.tagBits & TagBits.AnnotationNullMASK) == (providedType.tagBits & TagBits.AnnotationNullMASK);
}
// interpreting 'type' as a required type, compute the required null bits
@@ -205,22 +248,17 @@
}
if (type.isTypeVariable()) {
- // assume we must require @NonNull, unless: (1) lower @Nullable bound, or (2) no nullness specified
- TypeVariableBinding typeVariable = (TypeVariableBinding)type;
- boolean haveNullBits = false;
+ // assume we must require @NonNull, unless lower @Nullable bound
+ // (annotation directly on the TV has already been checked above)
if (type.isCapture()) {
TypeBinding lowerBound = ((CaptureBinding) type).lowerBound;
if (lowerBound != null) {
tagBits = lowerBound.tagBits & TagBits.AnnotationNullMASK;
if (tagBits == TagBits.AnnotationNullable)
- return TagBits.AnnotationNullable; // (1) type cannot require @NonNull
- haveNullBits = tagBits != 0;
+ return TagBits.AnnotationNullable; // type cannot require @NonNull
}
}
- if (typeVariable.firstBound != null)
- haveNullBits |= (typeVariable.firstBound.tagBits & TagBits.AnnotationNullMASK) != 0;
- if (haveNullBits)
- return TagBits.AnnotationNonNull; // could require @NonNull (unless (2) unspecified nullness)
+ return TagBits.AnnotationNonNull; // instantiation could require @NonNull
}
return 0;
@@ -375,4 +413,4 @@
}
return method;
}
-}
\ No newline at end of file
+}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
index 5e81242..7c2ea39 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
@@ -12,6 +12,7 @@
* bug 383368 - [compiler][null] syntactic null analysis for field references
* bug 403086 - [compiler][null] include the effect of 'assert' in syntactic null analysis for fields
* bug 403147 - [compiler][null] FUP of bug 400761: consolidate interaction between unboxing, NPE, and deferred checking
+ * Bug 422796 - [compiler][null] boxed boolean reported as potentially null after null test in lazy disjunction
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -74,7 +75,7 @@
if ((flowContext.tagBits & FlowContext.INSIDE_NEGATION) == 0)
flowContext.expireNullCheckedFieldInfo();
this.left.checkNPEbyUnboxing(currentScope, flowContext, flowInfo);
- this.right.checkNPEbyUnboxing(currentScope, flowContext, flowInfo);
+ this.right.checkNPEbyUnboxing(currentScope, flowContext, leftInfo.initsWhenFalse());
// The definitely null variables in right info when true should not be missed out while merging
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=299900
FlowInfo leftInfoWhenTrueForMerging = leftInfo.initsWhenTrue().unconditionalCopy().addPotentialInitializationsFrom(rightInfo.unconditionalInitsWithoutSideEffect());
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 40a44be..d1c0cb7 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -12,6 +12,7 @@
* 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 416181 – [1.8][compiler][null] Invalid assignment is not rejected by the compiler
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
* Andy Clement - Contributions for
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
*******************************************************************************/
@@ -146,7 +147,7 @@
/*
* No need to check for reference to raw type per construction
*/
- private TypeBinding internalResolveType(Scope scope, boolean checkBounds) {
+ private TypeBinding internalResolveType(Scope scope, boolean checkBounds, int location) {
// handle the error here
this.constant = Constant.NotAConstant;
if ((this.bits & ASTNode.DidResolve) != 0) { // is a shared type reference which was already resolved
@@ -169,7 +170,7 @@
this.bits |= ASTNode.DidResolve;
TypeBinding type = internalResolveLeafType(scope, checkBounds);
createArrayType(scope);
- resolveAnnotations(scope);
+ resolveAnnotations(scope, location);
if (this.typeArguments != null)
// relevant null annotations are on the inner most type:
checkNullConstraints(scope, this.typeArguments[this.typeArguments.length-1]);
@@ -420,11 +421,11 @@
return output;
}
- public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
- return internalResolveType(scope, checkBounds);
+ public TypeBinding resolveType(BlockScope scope, boolean checkBounds, int location) {
+ return internalResolveType(scope, checkBounds, location);
}
- public TypeBinding resolveType(ClassScope scope) {
- return internalResolveType(scope, false);
+ public TypeBinding resolveType(ClassScope scope, int location) {
+ return internalResolveType(scope, false, location);
}
public void traverse(ASTVisitor visitor, BlockScope scope) {
if (visitor.visit(this, 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 ea2c51f..2919b33 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
@@ -12,6 +12,7 @@
* Bug 420894 - ClassCastException in DefaultBindingResolver.resolveType(Type)
* 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 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
* Andy Clement - Contributions for
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
*******************************************************************************/
@@ -119,7 +120,7 @@
/*
* No need to check for reference to raw type per construction
*/
- private TypeBinding internalResolveType(Scope scope, ReferenceBinding enclosingType, boolean checkBounds) {
+ private TypeBinding internalResolveType(Scope scope, ReferenceBinding enclosingType, boolean checkBounds, int location) {
// handle the error here
this.constant = Constant.NotAConstant;
if ((this.bits & ASTNode.DidResolve) != 0) { // is a shared type reference which was already resolved
@@ -145,18 +146,18 @@
// handle three different outcomes:
if (type == null) {
this.resolvedType = createArrayType(scope, this.resolvedType);
- resolveAnnotations(scope);
+ resolveAnnotations(scope, 0); // no defaultNullness for buggy type
checkNullConstraints(scope, this.typeArguments);
- return null; // no useful type, but still captured dimensions into this.resolvedType
+ return null; // (1) no useful type, but still captured dimensions into this.resolvedType
} else {
type = createArrayType(scope, type);
if (!this.resolvedType.isValidBinding() && this.resolvedType.dimensions() == type.dimensions()) {
- resolveAnnotations(scope);
+ resolveAnnotations(scope, 0); // no defaultNullness for buggy type
checkNullConstraints(scope, this.typeArguments);
- return type; // found some error, but could recover useful type (like closestMatch)
+ return type; // (2) found some error, but could recover useful type (like closestMatch)
} else {
- this.resolvedType = type; // no complaint, keep fully resolved type (incl. dimensions)
- resolveAnnotations(scope);
+ this.resolvedType = type; // (3) no complaint, keep fully resolved type (incl. dimensions)
+ resolveAnnotations(scope, location);
checkNullConstraints(scope, this.typeArguments);
return this.resolvedType; // pick up any annotated type.
}
@@ -351,16 +352,16 @@
return output;
}
- public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
- return internalResolveType(scope, null, checkBounds);
+ public TypeBinding resolveType(BlockScope scope, boolean checkBounds, int location) {
+ return internalResolveType(scope, null, checkBounds, location);
}
- public TypeBinding resolveType(ClassScope scope) {
- return internalResolveType(scope, null, false /*no bounds check in classScope*/);
+ public TypeBinding resolveType(ClassScope scope, int location) {
+ return internalResolveType(scope, null, false /*no bounds check in classScope*/, location);
}
public TypeBinding resolveTypeEnclosing(BlockScope scope, ReferenceBinding enclosingType) {
- return internalResolveType(scope, enclosingType, true/*check bounds*/);
+ return internalResolveType(scope, enclosingType, true/*check bounds*/, 0);
}
public void traverse(ASTVisitor visitor, BlockScope scope) {
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 99a55d4..51a6378 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
@@ -73,6 +73,8 @@
public TypeReference [] typeArguments;
public char [] selector;
+ public int nameSourceStart;
+
public TypeBinding receiverType;
private boolean haveReceiver;
public TypeBinding[] resolvedTypeArguments;
@@ -356,6 +358,7 @@
this.lhs.bits |= ASTNode.IgnoreRawTypeCheck;
lhsType = this.lhs.resolveType(scope);
+ this.lhs.computeConversion(scope, lhsType, lhsType);
if (this.typeArguments != null) {
int length = this.typeArguments.length;
this.typeArgumentsHaveErrors = compilerOptions.sourceLevel < ClassFileConstants.JDK1_5;
@@ -395,7 +398,6 @@
lhsType = lhsType.closestMatch(); // improve resolving experience
if (!lhsType.isValidBinding())
return this.resolvedType = null; // nope, no useful type found
-
final TypeBinding[] descriptorParameters = this.descriptor != null ? this.descriptor.parameters : Binding.NO_PARAMETERS;
if (lhsType.isBaseType()) {
scope.problemReporter().errorNoMethodFor(this.lhs, lhsType, this.selector, descriptorParameters);
@@ -436,7 +438,7 @@
scope.problemReporter().invalidArrayConstructorReference(this, lhsType, descriptorParameters);
return this.resolvedType = null;
}
- if (!lhsType.isCompatibleWith(this.descriptor.returnType) && this.descriptor.returnType.id != TypeIds.T_void) {
+ if (this.descriptor.returnType.isProperType(true) && !lhsType.isCompatibleWith(this.descriptor.returnType) && this.descriptor.returnType.id != TypeIds.T_void) {
scope.problemReporter().constructedArrayIncompatible(this, lhsType, this.descriptor.returnType);
return this.resolvedType = null;
}
@@ -467,7 +469,7 @@
int someMethodDepth = this.depth, anotherMethodDepth = 0;
if (someMethod != null && someMethod.isValidBinding()) {
final boolean isStatic = someMethod.isStatic();
- if (isStatic && (this.haveReceiver || this.receiverType.isParameterizedType())) {
+ if (isStatic && (this.haveReceiver || this.receiverType.isParameterizedTypeWithActualArguments())) {
scope.problemReporter().methodMustBeAccessedStatically(this, someMethod);
return this.resolvedType = null;
}
@@ -647,14 +649,10 @@
/** During inference: Try to find an applicable method binding without causing undesired side-effects. */
public MethodBinding findCompileTimeMethodTargeting(TypeBinding targetType, Scope scope) {
- if (this.exactMethodBinding != null) {
- // TODO: shouldn't extactMethodBinding already be parameterized?
- if (this.exactMethodBinding.typeVariables != Binding.NO_TYPE_VARIABLES && this.resolvedTypeArguments != null) {
- return scope.environment().createParameterizedGenericMethod(this.exactMethodBinding, this.resolvedTypeArguments);
- }
- return this.exactMethodBinding;
- }
- return internalResolveTentatively(targetType, scope);
+ MethodBinding targetMethod = internalResolveTentatively(targetType, scope);
+ if (targetMethod == null || !targetMethod.isValidBinding())
+ return null;
+ return targetMethod;
}
MethodBinding internalResolveTentatively(TypeBinding targetType, Scope scope) {
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 f193e3d..038e860 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
@@ -29,6 +29,7 @@
* 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.
* Bug 427438 - [1.8][compiler] NPE at org.eclipse.jdt.internal.compiler.ast.ConditionalExpression.generateCode(ConditionalExpression.java:280)
+ * Bug 430150 - [1.8][null] stricter checking against type variables
* Jesper S Moller - Contributions for
* bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
*******************************************************************************/
@@ -81,7 +82,7 @@
if (this.expression != null) {
flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo);
this.expression.checkNPEbyUnboxing(currentScope, flowContext, flowInfo);
- if (flowInfo.reachMode() == FlowInfo.REACHABLE)
+ if (flowInfo.reachMode() == FlowInfo.REACHABLE && currentScope.compilerOptions().isAnnotationBasedNullAnalysisEnabled)
checkAgainstNullAnnotation(currentScope, flowContext, flowInfo);
if (currentScope.compilerOptions().analyseResourceLeaks) {
FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.expression, flowInfo, flowContext);
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 02c0273..6b58636 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
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for
* Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -78,7 +79,7 @@
this.resolvedType = scope.getMemberType(this.token, enclosingType);
boolean hasError = false;
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=391500
- resolveAnnotations(scope);
+ resolveAnnotations(scope, 0); // defaultNullness not relevant, the only caller within the compiler: QAE
TypeBinding memberType = this.resolvedType; // load after possible update in resolveAnnotations()
if (!memberType.isValidBinding()) {
hasError = true;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
index b3ed45c..4183c15 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchStatement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -65,7 +65,8 @@
try {
flowInfo = this.expression.analyseCode(currentScope, flowContext, flowInfo);
if ((this.expression.implicitConversion & TypeIds.UNBOXING) != 0
- || (this.expression.resolvedType != null && this.expression.resolvedType.id == T_JavaLangString)) {
+ || (this.expression.resolvedType != null
+ && (this.expression.resolvedType.id == T_JavaLangString || this.expression.resolvedType.isEnum()))) {
this.expression.checkNPE(currentScope, flowContext, flowInfo);
}
SwitchFlowContext switchContext =
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
index e40326c..7b516ee 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -1299,9 +1299,12 @@
outerScope = outerScope.parent;
}
} else if (existingType instanceof LocalTypeBinding
- && (((LocalTypeBinding) existingType).scope.methodScope() == blockScope.methodScope() || blockScope.isLambdaSubscope())) {
+ && ((LocalTypeBinding) existingType).scope.methodScope() == blockScope.methodScope()) {
// dup in same method
blockScope.problemReporter().duplicateNestedType(this);
+ } else if (existingType instanceof LocalTypeBinding && blockScope.isLambdaSubscope()
+ && blockScope.enclosingLambdaScope().enclosingMethodScope() == ((LocalTypeBinding) existingType).scope.methodScope()) {
+ blockScope.problemReporter().duplicateNestedType(this);
} else if (blockScope.isDefinedInType(existingType)) {
// collision with enclosing type
blockScope.problemReporter().typeCollidesWithEnclosingType(this);
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 7b5b2a9..5585832 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
@@ -15,6 +15,7 @@
* 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.
* Bug 427163 - [1.8][null] bogus error "Contradictory null specification" on varags
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
* 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
@@ -33,10 +34,13 @@
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
+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.LocalVariableBinding;
+import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReasons;
import org.eclipse.jdt.internal.compiler.lookup.ProblemReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
@@ -450,7 +454,7 @@
*/
public abstract char [][] getTypeName() ;
-protected TypeBinding internalResolveType(Scope scope) {
+protected TypeBinding internalResolveType(Scope scope, int location) {
// handle the error here
this.constant = Constant.NotAConstant;
if (this.resolvedType != null) { // is a shared type reference which was already resolved
@@ -501,12 +505,12 @@
scope.problemReporter().rawTypeReference(this, type);
}
if (hasError) {
- resolveAnnotations(scope);
+ resolveAnnotations(scope, 0); // don't apply null defaults to buggy type
return type;
} else {
// store the computed type only if no error, otherwise keep the problem type instead
this.resolvedType = type;
- resolveAnnotations(scope);
+ resolveAnnotations(scope, location);
return this.resolvedType; // pick up value that may have been changed in resolveAnnotations(..)
}
}
@@ -557,15 +561,23 @@
}
public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
- return internalResolveType(scope);
+ return resolveType(scope, checkBounds, 0);
+}
+
+public TypeBinding resolveType(BlockScope scope, boolean checkBounds, int location) {
+ return internalResolveType(scope, location);
}
public TypeBinding resolveType(ClassScope scope) {
- return internalResolveType(scope);
+ return resolveType(scope, 0);
+}
+
+public TypeBinding resolveType(ClassScope scope, int location) {
+ return internalResolveType(scope, location);
}
public TypeBinding resolveTypeArgument(BlockScope blockScope, ReferenceBinding genericType, int rank) {
- return resolveType(blockScope, true /* check bounds*/);
+ return resolveType(blockScope, true /* check bounds*/, Binding.DefaultLocationTypeArgument);
}
public TypeBinding resolveTypeArgument(ClassScope classScope, ReferenceBinding genericType, int rank) {
@@ -579,7 +591,7 @@
ref.tagBits |= TagBits.PauseHierarchyCheck;
pauseHierarchyCheck = true;
}
- return resolveType(classScope);
+ return resolveType(classScope, Binding.DefaultLocationTypeArgument);
} finally {
if (pauseHierarchyCheck) {
ref.tagBits &= ~TagBits.PauseHierarchyCheck;
@@ -591,7 +603,7 @@
public abstract void traverse(ASTVisitor visitor, ClassScope scope);
-protected void resolveAnnotations(Scope scope) {
+protected void resolveAnnotations(Scope scope, int location) {
Annotation[][] annotationsOnDimensions = getAnnotationsOnDimensions();
if (this.annotations != null || annotationsOnDimensions != null) {
BlockScope resolutionScope = Scope.typeAnnotationsResolutionScope(scope);
@@ -619,6 +631,17 @@
}
}
}
+ if (this.resolvedType != null
+ && (this.resolvedType.tagBits & TagBits.AnnotationNullMASK) == 0
+ && !this.resolvedType.isTypeVariable()
+ && !this.resolvedType.isWildcard()
+ && location != 0
+ && scope.hasDefaultNullnessFor(location))
+ {
+ LookupEnvironment environment = scope.environment();
+ AnnotationBinding[] annots = new AnnotationBinding[]{environment.getNonNullAnnotation()};
+ this.resolvedType = environment.createAnnotatedType(this.resolvedType, annots);
+ }
}
public int getAnnotatableLevels() {
return 1;
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 3eee697..1cc7d8a 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2012 IBM Corporation and others.
+ * Copyright (c) 2011, 2014 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
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -46,13 +48,13 @@
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.compiler.ast.TypeReference#getTypeBinding(org.eclipse.jdt.internal.compiler.lookup.Scope)
*/
- public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
+ public TypeBinding resolveType(BlockScope scope, boolean checkBounds, int location) {
// return the lub (least upper bound of all type binding)
int length = this.typeReferences.length;
TypeBinding[] allExceptionTypes = new TypeBinding[length];
boolean hasError = false;
for (int i = 0; i < length; i++) {
- TypeBinding exceptionType = this.typeReferences[i].resolveType(scope, checkBounds);
+ TypeBinding exceptionType = this.typeReferences[i].resolveType(scope, checkBounds, location);
if (exceptionType == null) {
return null;
}
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 22e6a5c..7f908cc 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -12,6 +12,7 @@
* 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.
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -62,15 +63,15 @@
TypeBinding boundType = null;
if (this.bound != null) {
boundType = scope.kind == Scope.CLASS_SCOPE
- ? this.bound.resolveType((ClassScope)scope)
- : this.bound.resolveType((BlockScope)scope, true /* check bounds*/);
+ ? this.bound.resolveType((ClassScope)scope, Binding.DefaultLocationTypeBound)
+ : this.bound.resolveType((BlockScope)scope, true /* check bounds*/, Binding.DefaultLocationTypeBound);
this.bits |= (this.bound.bits & ASTNode.HasTypeAnnotations);
if (boundType == null) {
return null;
}
}
this.resolvedType = scope.environment().createWildcard(genericType, rank, boundType, null /*no extra bound*/, this.kind);
- resolveAnnotations(scope);
+ resolveAnnotations(scope, 0); // no defaultNullness for wildcards
if (boundType != null && boundType.hasNullTypeAnnotations() && this.resolvedType.hasNullTypeAnnotations()) {
if (((boundType.tagBits | this.resolvedType.tagBits) & TagBits.AnnotationNullMASK) == TagBits.AnnotationNullMASK) { // are both set?
Annotation annotation = this.bound.findAnnotation(boundType.tagBits & TagBits.AnnotationNullMASK);
@@ -102,27 +103,27 @@
}
// only invoked for improving resilience when unable to bind generic type from parameterized reference
- public TypeBinding resolveType(BlockScope scope, boolean checkBounds) {
+ public TypeBinding resolveType(BlockScope scope, boolean checkBounds, int location) {
if (this.bound != null) {
- this.bound.resolveType(scope, checkBounds);
+ this.bound.resolveType(scope, checkBounds, Binding.DefaultLocationTypeBound);
this.bits |= (this.bound.bits & ASTNode.HasTypeAnnotations);
}
return null;
}
// only invoked for improving resilience when unable to bind generic type from parameterized reference
- public TypeBinding resolveType(ClassScope scope) {
+ public TypeBinding resolveType(ClassScope scope, int location) {
if (this.bound != null) {
- this.bound.resolveType(scope);
+ this.bound.resolveType(scope, Binding.DefaultLocationTypeBound);
this.bits |= (this.bound.bits & ASTNode.HasTypeAnnotations);
}
return null;
}
public TypeBinding resolveTypeArgument(BlockScope blockScope, ReferenceBinding genericType, int rank) {
- return internalResolveType(blockScope, genericType, rank);
+ return internalResolveType(blockScope, genericType, rank); // no defaultNullness for wildcards
}
public TypeBinding resolveTypeArgument(ClassScope classScope, ReferenceBinding genericType, int rank) {
- return internalResolveType(classScope, genericType, rank);
+ return internalResolveType(classScope, genericType, rank); // no defaultNullness for wildcards
}
public void traverse(ASTVisitor visitor, BlockScope scope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
new file mode 100644
index 0000000..fd8105b
--- /dev/null
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/classfmt/NonNullDefaultAwareTypeAnnotationWalker.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2014 GK Software AG.
+ * 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
+ *
+ * Contributors:
+ * Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.classfmt;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation;
+import org.eclipse.jdt.internal.compiler.env.IBinaryElementValuePair;
+import org.eclipse.jdt.internal.compiler.env.IBinaryTypeAnnotation;
+import org.eclipse.jdt.internal.compiler.lookup.Binding;
+import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
+
+/**
+ * A type annotation walker that adds missing NonNull annotations according to the current default.
+ */
+public class NonNullDefaultAwareTypeAnnotationWalker extends TypeAnnotationWalker {
+
+ private int defaultNullness;
+ private boolean atDefaultLocation;
+ private boolean nextIsDefaultLocation;
+ private boolean isEmpty;
+ IBinaryAnnotation nonNullAnnotation;
+
+ /** Create initial walker with non-empty type annotations. */
+ public NonNullDefaultAwareTypeAnnotationWalker(IBinaryTypeAnnotation[] typeAnnotations,
+ int defaultNullness, LookupEnvironment environment) {
+ super(typeAnnotations);
+ this.nonNullAnnotation = getNonNullAnnotation(environment);
+ this.defaultNullness = defaultNullness;
+ }
+
+ /** Create an initial walker without 'real' type annotations, but with a nonnull default. */
+ public NonNullDefaultAwareTypeAnnotationWalker(int defaultNullness, LookupEnvironment environment) {
+ this(defaultNullness, getNonNullAnnotation(environment), false);
+ }
+
+ /** Get restricted walker, still with non-empty type annotations. */
+ NonNullDefaultAwareTypeAnnotationWalker(IBinaryTypeAnnotation[] typeAnnotations, long newMatches, int newPathPtr,
+ int defaultNullness, IBinaryAnnotation nonNullAnnotation, boolean atDefaultLocation) {
+ super(typeAnnotations, newMatches, newPathPtr);
+ this.defaultNullness = defaultNullness;
+ this.nonNullAnnotation = nonNullAnnotation;
+ this.atDefaultLocation = atDefaultLocation;
+ }
+
+ /** Create a restricted walker without 'real' type annotations, but with a nonnull default. */
+ NonNullDefaultAwareTypeAnnotationWalker(int defaultNullness, IBinaryAnnotation nonNullAnnotation, boolean atDefaultLocation) {
+ super(null, 0, 0);
+ this.nonNullAnnotation = nonNullAnnotation;
+ this.defaultNullness = defaultNullness;
+ this.atDefaultLocation = atDefaultLocation;
+ this.isEmpty = true;
+ }
+
+ private static IBinaryAnnotation getNonNullAnnotation(LookupEnvironment environment) {
+ final char[] nonNullAnnotationName = CharOperation.concat(
+ 'L', CharOperation.concatWith(environment.getNonNullAnnotationName(), '/'), ';');
+ // create the synthetic annotation:
+ return new IBinaryAnnotation() {
+ @Override
+ public char[] getTypeName() {
+ return nonNullAnnotationName;
+ }
+ @Override
+ public IBinaryElementValuePair[] getElementValuePairs() {
+ return null;
+ }
+ };
+ }
+
+ protected TypeAnnotationWalker restrict(long newMatches, int newPathPtr) {
+ // considers nextIsDefaultLocation as the new atDefaultLocation
+ try {
+ // do we have any change at all?
+ if (this.matches == newMatches && this.pathPtr == newPathPtr && this.atDefaultLocation == this.nextIsDefaultLocation)
+ return this;
+ // are we running out of real type annotations?
+ if (newMatches == 0 || this.typeAnnotations == null || this.typeAnnotations.length == 0)
+ return new NonNullDefaultAwareTypeAnnotationWalker(this.defaultNullness, this.nonNullAnnotation, this.nextIsDefaultLocation);
+ // proceed as normal, but pass on our specific fields, too:
+ return new NonNullDefaultAwareTypeAnnotationWalker(this.typeAnnotations, newMatches, newPathPtr,
+ this.defaultNullness, this.nonNullAnnotation, this.nextIsDefaultLocation);
+ } finally {
+ this.nextIsDefaultLocation = false; // expire
+ }
+ }
+
+ @Override
+ public TypeAnnotationWalker toMethodParameter(short index) {
+ // don't set nextIsDefaultLocation, because signature-level nullness is handled by ImplicitNullAnnotationVerifier
+ if (this.isEmpty) return restrict(this.matches, this.pathPtr);
+ return super.toMethodParameter(index);
+ }
+
+ @Override
+ public TypeAnnotationWalker toMethodReturn() {
+ // don't set nextIsDefaultLocation, because signature-level nullness is handled by ImplicitNullAnnotationVerifier
+ if (this.isEmpty) return restrict(this.matches, this.pathPtr);
+ return super.toMethodReturn();
+ }
+
+ @Override
+ public TypeAnnotationWalker toTypeBound(short boundIndex) {
+ this.nextIsDefaultLocation = (this.defaultNullness & Binding.DefaultLocationTypeBound) != 0;
+ if (this.isEmpty) return restrict(this.matches, this.pathPtr);
+ return super.toTypeBound(boundIndex);
+ }
+
+ @Override
+ public TypeAnnotationWalker toTypeParameterBounds(boolean isClassTypeParameter, int parameterRank) {
+ this.nextIsDefaultLocation = (this.defaultNullness & Binding.DefaultLocationTypeBound) != 0;
+ if (this.isEmpty) return restrict(this.matches, this.pathPtr);
+ return super.toTypeParameterBounds(isClassTypeParameter, parameterRank);
+ }
+
+ @Override
+ public TypeAnnotationWalker toTypeArgument(int rank) {
+ this.nextIsDefaultLocation = (this.defaultNullness & Binding.DefaultLocationTypeArgument) != 0;
+ if (this.isEmpty) return restrict(this.matches, this.pathPtr);
+ return super.toTypeArgument(rank);
+ }
+
+ @Override
+ public TypeAnnotationWalker toTypeParameter(boolean isClassTypeParameter, int rank) {
+ this.nextIsDefaultLocation = (this.defaultNullness & Binding.DefaultLocationTypeParameter) != 0;
+ if (this.isEmpty) return restrict(this.matches, this.pathPtr);
+ return super.toTypeParameter(isClassTypeParameter, rank);
+ }
+
+ @Override
+ public IBinaryAnnotation[] getAnnotationsAtCursor() {
+ IBinaryAnnotation[] normalAnnotations = this.isEmpty ? null : super.getAnnotationsAtCursor();
+ if (this.atDefaultLocation) {
+ if (normalAnnotations == null || normalAnnotations.length == 0)
+ return new IBinaryAnnotation[] { this.nonNullAnnotation };
+ int len = normalAnnotations.length;
+ IBinaryAnnotation[] newAnnots = new IBinaryAnnotation[len+1];
+ System.arraycopy(normalAnnotations, 0, newAnnots, 0, len);
+ newAnnots[len] = this.nonNullAnnotation;
+ return newAnnots;
+ }
+ return normalAnnotations;
+ }
+}
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 e727e80..9f189b7 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 GK Software AG.
+ * Copyright (c) 2013, 2014 GK Software AG.
* 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
@@ -44,9 +44,9 @@
public IBinaryAnnotation[] getAnnotationsAtCursor() { return NO_ANNOTATIONS; }
};
- final private IBinaryTypeAnnotation[] typeAnnotations; // the actual material we're managing here
- final private long matches; // bit mask of indices into typeAnnotations, 1 means active, 0 is filtered during the walk
- final private int pathPtr; // pointer into the typePath
+ final protected IBinaryTypeAnnotation[] typeAnnotations; // the actual material we're managing here
+ final protected long matches; // bit mask of indices into typeAnnotations, 1 means active, 0 is filtered during the walk
+ final protected int pathPtr; // pointer into the typePath
// precondition: not-empty typeAnnotations
public TypeAnnotationWalker(IBinaryTypeAnnotation[] typeAnnotations) {
@@ -55,13 +55,13 @@
TypeAnnotationWalker(IBinaryTypeAnnotation[] typeAnnotations, long matchBits) {
this(typeAnnotations, matchBits, 0);
}
- private TypeAnnotationWalker(IBinaryTypeAnnotation[] typeAnnotations, long matchBits, int pathPtr) {
+ protected TypeAnnotationWalker(IBinaryTypeAnnotation[] typeAnnotations, long matchBits, int pathPtr) {
this.typeAnnotations = typeAnnotations;
this.matches = matchBits;
this.pathPtr = pathPtr;
}
- private TypeAnnotationWalker restrict(long newMatches, int newPathPtr) {
+ protected TypeAnnotationWalker restrict(long newMatches, int newPathPtr) {
if (this.matches == newMatches && this.pathPtr == newPathPtr) return this;
if (newMatches == 0 || this.typeAnnotations == null || this.typeAnnotations.length == 0)
return EMPTY_ANNOTATION_WALKER;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java
index f10a187..d413dc7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/env/ISourceType.java
@@ -87,4 +87,9 @@
* Answer the names of the receiver's type parameters.
*/
char[][] getTypeParameterNames();
+
+/**
+ * Answer whether the receiver type is anonymous
+ */
+boolean isAnonymous();
}
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 7a4086b..fa85a8b 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
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * Bug 432977 - [1.8][null] Incorrect 'type is not visible' compiler error
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -318,6 +320,9 @@
break;
}
if (Util.effectivelyEqual(derivedType.getTypeAnnotations(), annotations)) {
+ // point-fix for https://bugs.eclipse.org/432977
+ if (!type.isUnresolvedType() && derivedType.isUnresolvedType())
+ return ((UnresolvedReferenceBinding)derivedType).resolve(this.environment, false);
return derivedType;
}
if (!derivedType.hasTypeAnnotations())
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 b1536ab..4124f49 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
@@ -438,6 +438,13 @@
public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType, LookupEnvironment env) {
if (this.leafComponentType == unresolvedType) { //$IDENTITY-COMPARISON$
this.leafComponentType = env.convertUnresolvedBinaryToRawType(resolvedType);
+ /* Leaf component type is the key in the type system. If it undergoes change, the array has to be rehashed.
+ We achieve by creating a fresh array with the new component type and equating this array's id with that.
+ This means this array can still be found under the old key, but that is harmless (since the component type
+ is always consulted (see TypeSystem.getArrayType())
+ */
+ if (this.leafComponentType != resolvedType) //$IDENTITY-COMPARISON$
+ this.id = env.createArrayType(this.leafComponentType, this.dimensions, this.typeAnnotations).id;
this.tagBits |= this.leafComponentType.tagBits & (TagBits.HasTypeVariable | TagBits.HasDirectWildcard | TagBits.HasMissingType | TagBits.HasCapturedWildcard);
}
}
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 90615c7..9f6fc74 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
@@ -24,6 +24,8 @@
* Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Bug 427199 - [1.8][resource] avoid resource leak warnings on Streams that have no resource
* Bug 392245 - [1.8][compiler][null] Define whether / how @NonNullByDefault applies to TYPE_USE locations
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
+ * Bug 390889 - [1.8][compiler] Evaluate options to support 1.7- projects against 1.8 JRE.
* 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
@@ -33,7 +35,9 @@
import java.util.ArrayList;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.classfmt.NonNullDefaultAwareTypeAnnotationWalker;
import org.eclipse.jdt.internal.compiler.classfmt.TypeAnnotationWalker;
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
import org.eclipse.jdt.internal.compiler.env.*;
@@ -79,8 +83,9 @@
protected SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder
private ReferenceBinding containerAnnotationType;
+ int defaultNullness = 0;
-static Object convertMemberValue(Object binaryValue, LookupEnvironment env, char[][][] missingTypeNames) {
+static Object convertMemberValue(Object binaryValue, LookupEnvironment env, char[][][] missingTypeNames, boolean resolveEnumConstants) {
if (binaryValue == null) return null;
if (binaryValue instanceof Constant)
return binaryValue;
@@ -91,6 +96,8 @@
if (binaryValue instanceof EnumConstantSignature) {
EnumConstantSignature ref = (EnumConstantSignature) binaryValue;
ReferenceBinding enumType = (ReferenceBinding) env.getTypeFromSignature(ref.getTypeName(), 0, -1, false, null, missingTypeNames, TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
+ if (enumType.isUnresolvedType() && !resolveEnumConstants)
+ return new ElementValuePair.UnresolvedEnumConstant(enumType, env, ref.getEnumConstantName());
enumType = (ReferenceBinding) resolveType(enumType, env, false /* no raw conversion */);
return enumType.getField(ref.getEnumConstantName(), false);
}
@@ -100,7 +107,7 @@
if (length == 0) return objects;
Object[] values = new Object[length];
for (int i = 0; i < length; i++)
- values[i] = convertMemberValue(objects[i], env, missingTypeNames);
+ values[i] = convertMemberValue(objects[i], env, missingTypeNames, resolveEnumConstants);
return values;
}
@@ -132,7 +139,7 @@
int length = binaryPairs == null ? 0 : binaryPairs.length;
ElementValuePair[] pairs = length == 0 ? Binding.NO_ELEMENT_VALUE_PAIRS : new ElementValuePair[length];
for (int i = 0; i < length; i++)
- pairs[i] = new ElementValuePair(binaryPairs[i].getName(), convertMemberValue(binaryPairs[i].getValue(), env, missingTypeNames), null);
+ pairs[i] = new ElementValuePair(binaryPairs[i].getName(), convertMemberValue(binaryPairs[i].getValue(), env, missingTypeNames, false), null);
char[] typeName = annotationInfo.getTypeName();
ReferenceBinding annotationType = env.getTypeFromConstantPoolName(typeName, 1, typeName.length - 1, false, missingTypeNames);
@@ -393,6 +400,10 @@
and/or super interfaces in order to be able to detect overriding in the presence
of generics.
*/
+ if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
+ // need annotations on the type before processing null annotations on members respecting any @NonNullByDefault:
+ scanTypeForNullDefaultAnnotation(binaryType, this.fPackage, this);
+ }
TypeAnnotationWalker walker = getTypeAnnotationWalker(binaryType.getTypeAnnotations());
char[] typeSignature = binaryType.getGenericSignature(); // use generic signature even in 1.4
this.tagBits |= binaryType.getTagBits();
@@ -480,9 +491,6 @@
}
}
if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
- // need annotations on the type before processing null annotations on members respecting any @NonNullByDefault:
- scanTypeForNullDefaultAnnotation(binaryType, this.fPackage, this);
-
if (iFields != null) {
for (int i = 0; i < iFields.length; i++)
scanFieldForNullAnnotation(iFields[i], this.fields[i], this.isEnum());
@@ -508,10 +516,20 @@
private TypeAnnotationWalker getTypeAnnotationWalker(IBinaryTypeAnnotation[] annotations) {
if (!isPrototype()) throw new IllegalStateException();
- if (annotations == null || annotations.length == 0)
+ if (annotations == null || annotations.length == 0 || !this.environment.usesAnnotatedTypeSystem()) {
+ if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
+ int nullness = getNullDefault();
+ if (nullness > Binding.NULL_UNSPECIFIED_BY_DEFAULT)
+ return new NonNullDefaultAwareTypeAnnotationWalker(nullness, this.environment);
+ }
return TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
-
- return this.environment.usesAnnotatedTypeSystem() ? new TypeAnnotationWalker(annotations) : TypeAnnotationWalker.EMPTY_ANNOTATION_WALKER;
+ }
+ if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
+ int nullness = getNullDefault();
+ if (nullness > Binding.NULL_UNSPECIFIED_BY_DEFAULT)
+ return new NonNullDefaultAwareTypeAnnotationWalker(annotations, nullness, this.environment);
+ }
+ return new TypeAnnotationWalker(annotations);
}
private void createFields(IBinaryField[] iFields, long sourceLevel, char[][][] missingTypeNames) {
@@ -575,13 +593,10 @@
if (sourceLevel < ClassFileConstants.JDK1_5)
methodModifiers &= ~ClassFileConstants.AccVarargs; // vararg methods are not recognized until 1.5
if (isInterface() && (methodModifiers & ClassFileConstants.AccAbstract) == 0) {
- // see https://bugs.eclipse.org/388954
- if (sourceLevel >= ClassFileConstants.JDK1_8) {
- if ((methodModifiers & ClassFileConstants.AccStatic) == 0) {
- methodModifiers |= ExtraCompilerModifiers.AccDefaultMethod;
- }
- } else {
- methodModifiers |= ClassFileConstants.AccAbstract;
+ // see https://bugs.eclipse.org/388954 superseded by https://bugs.eclipse.org/390889
+ if ((methodModifiers & ClassFileConstants.AccStatic) == 0) {
+ // i.e. even at 1.7- we record AccDefaultMethod when reading a 1.8+ interface to avoid errors caused by default methods added to a library
+ methodModifiers |= ExtraCompilerModifiers.AccDefaultMethod;
}
}
ReferenceBinding[] exceptions = Binding.NO_EXCEPTIONS;
@@ -643,12 +658,7 @@
// 'paramAnnotations' line up with 'parameters'
// int parameter to method.getParameterAnnotations() include the synthetic arg
if (paramAnnotations != null)
- // BUGFIX PICKED UP? NO NEED TO PATCH ANYMORE?
-// /* Aspectj extension start:309440: was:
paramAnnotations[i - startIndex] = createAnnotations(method.getParameterAnnotations(i - startIndex), this.environment, missingTypeNames);
-// // now */
-// paramAnnotations[i - startIndex] = createAnnotations(method.getParameterAnnotations(i-startIndex), this.environment);
-// // AspectJ extension end
}
index = end + 1;
}
@@ -801,7 +811,7 @@
result.setAnnotations(
createAnnotations(annotations, this.environment, missingTypeNames),
paramAnnotations,
- isAnnotationType() ? convertMemberValue(method.getDefaultValue(), this.environment, missingTypeNames) : null,
+ isAnnotationType() ? convertMemberValue(method.getDefaultValue(), this.environment, missingTypeNames, true) : null,
this.environment);
}
@@ -1117,6 +1127,7 @@
public FieldBinding getFieldBase(char[] fieldName, boolean needResolve) { // AspectJ Extension - added Base to name
if (!isPrototype())
return this.prototype.getField(fieldName, needResolve);
+
// lazily sort fields
if ((this.tagBits & TagBits.AreFieldsSorted) == 0) {
int length = this.fields.length;
@@ -1153,8 +1164,10 @@
}
// NOTE: the return type, arg & exception types of each method of a binary type are resolved when needed
public MethodBinding[] getMethodsBase(char[] selector) { // AspectJ Extension - added Base to name
- if (!isPrototype())
- return this.prototype.getMethods(selector);
+
+ if (!isPrototype())
+ return this.prototype.getMethods(selector);
+
if ((this.tagBits & TagBits.AreMethodsComplete) != 0) {
long range;
if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
@@ -1518,7 +1531,7 @@
if (fieldType != null
&& !fieldType.isBaseType()
&& (fieldType.tagBits & TagBits.AnnotationNullMASK) == 0
- && (this.tagBits & TagBits.AnnotationNonNullByDefault) != 0) {
+ && hasNonNullDefaultFor(DefaultLocationField, true)) {
fieldBinding.type = this.environment.createAnnotatedType(fieldType, new AnnotationBinding[]{this.environment.getNonNullAnnotation()});
}
return; // not using fieldBinding.tagBits when we have type annotations.
@@ -1586,6 +1599,8 @@
char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
if (CharOperation.equals(typeName, nonNullByDefaultAnnotationName)) {
methodBinding.tagBits |= TagBits.AnnotationNonNullByDefault;
+ if (useTypeAnnotations)
+ methodBinding.defaultNullness = getNonNullByDefaultValue(annotations[i]);
}
if (!useTypeAnnotations && !explicitNullness) {
if (CharOperation.equals(typeName, nonNullAnnotationName)) {
@@ -1634,6 +1649,7 @@
}
}
}
+// pre: null annotation analysis is enabled
private void scanTypeForNullDefaultAnnotation(IBinaryType binaryType, PackageBinding packageBinding, BinaryTypeBinding binaryBinding) {
if (!isPrototype()) throw new IllegalStateException();
char[][] nonNullByDefaultAnnotationName = this.environment.getNonNullByDefaultAnnotationName();
@@ -1642,6 +1658,7 @@
IBinaryAnnotation[] annotations = binaryType.getAnnotations();
boolean isPackageInfo = CharOperation.equals(binaryBinding.sourceName(), TypeConstants.PACKAGE_INFO_NAME);
+ boolean useTypeAnnotations = this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8;
if (annotations != null) {
long annotationBit = 0L;
int nullness = NO_NULL_DEFAULT;
@@ -1653,21 +1670,28 @@
char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
if (CharOperation.equals(typeName, nonNullByDefaultAnnotationName)) {
IBinaryElementValuePair[] elementValuePairs = annotations[i].getElementValuePairs();
- if (elementValuePairs != null && elementValuePairs.length == 1) {
- Object value = elementValuePairs[0].getValue();
- if (value instanceof BooleanConstant
- && !((BooleanConstant)value).booleanValue())
- {
- // parameter is 'false': this means we cancel defaults from outer scopes:
- annotationBit = TagBits.AnnotationNullUnspecifiedByDefault;
- nullness = NULL_UNSPECIFIED_BY_DEFAULT;
- break;
- } else if (value instanceof Object[] && ((Object[])value).length == 0) {
- // parameter is '{}': this means we cancel defaults from outer scopes:
- annotationBit = TagBits.AnnotationNullUnspecifiedByDefault;
- nullness = NULL_UNSPECIFIED_BY_DEFAULT;
- break;
+ if (!useTypeAnnotations) {
+ if (elementValuePairs != null && elementValuePairs.length == 1) {
+ Object value = elementValuePairs[0].getValue();
+ if (value instanceof BooleanConstant
+ && !((BooleanConstant)value).booleanValue())
+ {
+ // parameter is 'false': this means we cancel defaults from outer scopes:
+ annotationBit = TagBits.AnnotationNullUnspecifiedByDefault;
+ nullness = NULL_UNSPECIFIED_BY_DEFAULT;
+ break;
+ }
}
+ } else {
+ // using NonNullByDefault we need to inspect the details of the value() attribute:
+ nullness = getNonNullByDefaultValue(annotations[i]);
+ if (nullness == NULL_UNSPECIFIED_BY_DEFAULT) {
+ annotationBit = TagBits.AnnotationNullUnspecifiedByDefault;
+ } else if (nullness != 0) {
+ annotationBit = TagBits.AnnotationNonNullByDefault;
+ }
+ this.defaultNullness = nullness;
+ break;
}
annotationBit = TagBits.AnnotationNonNullByDefault;
nullness = NONNULL_BY_DEFAULT;
@@ -1688,12 +1712,19 @@
}
ReferenceBinding enclosingTypeBinding = binaryBinding.enclosingType;
if (enclosingTypeBinding != null) {
- if ((enclosingTypeBinding.tagBits & TagBits.AnnotationNonNullByDefault) != 0) {
- binaryBinding.tagBits |= TagBits.AnnotationNonNullByDefault;
- return;
- } else if ((enclosingTypeBinding.tagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0) {
- binaryBinding.tagBits |= TagBits.AnnotationNullUnspecifiedByDefault;
- return;
+ if (useTypeAnnotations) {
+ binaryBinding.defaultNullness = enclosingTypeBinding.getNullDefault();
+ if (binaryBinding.defaultNullness != 0) {
+ return;
+ }
+ } else {
+ if ((enclosingTypeBinding.tagBits & TagBits.AnnotationNonNullByDefault) != 0) {
+ binaryBinding.tagBits |= TagBits.AnnotationNonNullByDefault;
+ return;
+ } else if ((enclosingTypeBinding.tagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0) {
+ binaryBinding.tagBits |= TagBits.AnnotationNullUnspecifiedByDefault;
+ return;
+ }
}
}
// no annotation found on the type or its enclosing types
@@ -1706,16 +1737,55 @@
}
}
// no @NonNullByDefault at type level, check containing package:
- switch (packageBinding.defaultNullness) {
- case Binding.NONNULL_BY_DEFAULT :
- binaryBinding.tagBits |= TagBits.AnnotationNonNullByDefault;
- break;
- case Binding.NULL_UNSPECIFIED_BY_DEFAULT :
- binaryBinding.tagBits |= TagBits.AnnotationNullUnspecifiedByDefault;
- break;
+ if (useTypeAnnotations) {
+ binaryBinding.defaultNullness = packageBinding.defaultNullness;
+ } else {
+ switch (packageBinding.defaultNullness) {
+ case Binding.NONNULL_BY_DEFAULT :
+ binaryBinding.tagBits |= TagBits.AnnotationNonNullByDefault;
+ break;
+ case Binding.NULL_UNSPECIFIED_BY_DEFAULT :
+ binaryBinding.tagBits |= TagBits.AnnotationNullUnspecifiedByDefault;
+ break;
+ }
}
}
+/** given an application of @NonNullByDefault convert the annotation argument (if any) into a bitvector a la {@link Binding#NullnessDefaultMASK} */
+// pre: null annotation analysis is enabled
+int getNonNullByDefaultValue(IBinaryAnnotation annotation) {
+ char[] annotationTypeName = annotation.getTypeName();
+ char[][] typeName = CharOperation.splitOn('/', annotationTypeName, 1, annotationTypeName.length-1); // cut of leading 'L' and trailing ';'
+ IBinaryElementValuePair[] elementValuePairs = annotation.getElementValuePairs();
+ if (elementValuePairs == null || elementValuePairs.length == 0 ) {
+ // no argument: apply default default
+ ReferenceBinding annotationType = this.environment.getType(typeName);
+ if (annotationType == null) return 0;
+ if (annotationType.isUnresolvedType())
+ annotationType = ((UnresolvedReferenceBinding) annotationType).resolve(this.environment, false);
+ MethodBinding[] annotationMethods = annotationType.methods();
+ if (annotationMethods != null && annotationMethods.length == 1) {
+ Object value = annotationMethods[0].getDefaultValue();
+ return Annotation.nullTagBitsFromAnnotationValue(value);
+ }
+ } else if (elementValuePairs.length > 0) {
+ // evaluate the contained EnumConstantSignatures:
+ int nullness = 0;
+ for (int i = 0; i < elementValuePairs.length; i++)
+ nullness |= Annotation.nullTagBitsFromAnnotationValue(elementValuePairs[i].getValue());
+ return nullness;
+ } else {
+ // empty argument: cancel all defaults from enclosing scopes
+ return NULL_UNSPECIFIED_BY_DEFAULT;
+ }
+ return 0;
+}
+
+@Override
+int getNullDefault() {
+ return this.defaultNullness;
+}
+
private void scanTypeForContainerAnnotation(IBinaryType binaryType, char[][][] missingTypeNames) {
if (!isPrototype()) throw new IllegalStateException();
IBinaryAnnotation[] annotations = binaryType.getAnnotations();
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 4d395fc..08abc3e 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -10,6 +10,7 @@
* Stephan Herrmann - Contribution for
* bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
* Bug 400874 - [1.8][compiler] Inference infrastructure should evolve to meet JLS8 18.x (Part G of JSR335 spec)
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
* Jesper Steen Moller - Contributions for
* Bug 412150 [1.8] [compiler] Enable reflected parameter names during annotation processing
*******************************************************************************/
@@ -66,8 +67,44 @@
// Nullness defaults:
public static final int NO_NULL_DEFAULT = 0;
- public static final int NULL_UNSPECIFIED_BY_DEFAULT = 1;
- public static final int NONNULL_BY_DEFAULT = 2;
+ // SE5 style:
+ public static final int NONNULL_BY_DEFAULT = 1;
+ public static final int NULL_UNSPECIFIED_BY_DEFAULT = 2;
+ // JSR308 style:
+ /**
+ * Bit in defaultNullness bit vectors, representing the enum constant DefaultLocation#PARAMETER
+ */
+ public static final int DefaultLocationParameter = ASTNode.Bit4;
+ /**
+ * Bit in defaultNullness bit vectors, representing the enum constant DefaultLocation#RETURN_TYPE
+ */
+ public static final int DefaultLocationReturnType = ASTNode.Bit5;
+ /**
+ * Bit in defaultNullness bit vectors, representing the enum constant DefaultLocation#FIELD
+ */
+ public static final int DefaultLocationField = ASTNode.Bit6;
+ /**
+ * Bit in defaultNullness bit vectors, representing the enum constant DefaultLocation#TYPE_ARGUMENT
+ */
+ public static final int DefaultLocationTypeArgument = ASTNode.Bit7;
+ /**
+ * Bit in defaultNullness bit vectors, representing the enum constant DefaultLocation#TYPE_PARAMETER
+ */
+ public static final int DefaultLocationTypeParameter = ASTNode.Bit8;
+ /**
+ * Bit in defaultNullness bit vectors, representing the enum constant DefaultLocation#TYPE_BOUND
+ */
+ public static final int DefaultLocationTypeBound = ASTNode.Bit9;
+ /**
+ * Bit in defaultNullness bit vectors, representing the enum constant DefaultLocation#ARRAY_CONTENTS
+ * TODO: this constant is not yet used, due to difficulty to discern these annotations between SE5 / SE8
+ */
+ public static final int DefaultLocationArrayContents = ASTNode.Bit10;
+
+ public static final int NullnessDefaultMASK =
+ NULL_UNSPECIFIED_BY_DEFAULT | // included to terminate search up the parent chain
+ DefaultLocationParameter | DefaultLocationReturnType | DefaultLocationField |
+ DefaultLocationTypeArgument | DefaultLocationTypeParameter | DefaultLocationTypeBound | DefaultLocationArrayContents;
/*
* Answer the receiver's binding type from Binding.BindingID.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
index 44c04cf..d518762 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -17,6 +17,7 @@
* bug 379784 - [compiler] "Method can be static" is not getting reported
* bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional
* bug 404649 - [1.8][compiler] detect illegal reference to indirect or redundant super
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
* Jesper S Moller <jesper@selskabet.org> - Contributions for
* bug 378674 - "The method can be declared as static" is wrong
* Keigo Imai - Contribution for bug 388903 - Cannot extend inner class as an anonymous class when it extends the outer class
@@ -61,6 +62,9 @@
public final static VariableBinding[] NoEnclosingInstanceInStaticContext = {};
+ // annotation support
+ public boolean insideTypeAnnotation = false;
+
public BlockScope(BlockScope parent) {
this(parent, true);
}
@@ -99,7 +103,7 @@
MethodScope methodScope = methodScope();
while (methodScope != null && methodScope.referenceContext instanceof LambdaExpression) {
LambdaExpression lambda = (LambdaExpression) methodScope.referenceContext;
- if (!lambda.scope.isStatic) {
+ if (!lambda.scope.isStatic && !lambda.scope.isConstructorCall) {
lambda.shouldCaptureInstance = true;
}
methodScope = methodScope.enclosingMethodScope();
@@ -117,7 +121,7 @@
MethodScope methodScope = methodScope();
while (methodScope != null && methodScope.referenceContext instanceof LambdaExpression) {
LambdaExpression lambda = (LambdaExpression) methodScope.referenceContext;
- if (!lambda.scope.isStatic) {
+ if (!lambda.scope.isStatic && !lambda.scope.isConstructorCall) {
lambda.shouldCaptureInstance = true;
}
methodScope = methodScope.enclosingMethodScope();
@@ -1232,4 +1236,8 @@
}
return true;
}
+@Override
+public boolean hasDefaultNullnessFor(int location) {
+ return this.parent.hasDefaultNullnessFor(location);
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
index 2a513e5..24f9b2a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java
@@ -233,11 +233,17 @@
* which only happens if null annotations are enabled in the first place.
*/
private void useNullHints(long nullHints, TypeBinding[] boundTypes, LookupEnvironment environment) {
- AnnotationBinding[] annot = environment.nullAnnotationsFromTagBits(nullHints);
- if (annot != null) {
- // only get here if exactly one of @NonNull or @Nullable was hinted; now apply this hint:
+ if (nullHints == TagBits.AnnotationNullMASK) {
+ // on contradiction remove null type annotations
for (int i = 0; i < boundTypes.length; i++)
- boundTypes[i] = environment.createAnnotatedType(boundTypes[i], annot);
+ boundTypes[i] = boundTypes[i].unannotated();
+ } else {
+ AnnotationBinding[] annot = environment.nullAnnotationsFromTagBits(nullHints);
+ if (annot != null) {
+ // only get here if exactly one of @NonNull or @Nullable was hinted; now apply this hint:
+ for (int i = 0; i < boundTypes.length; i++)
+ boundTypes[i] = environment.createAnnotatedType(boundTypes[i], annot);
+ }
}
}
TypeBinding combineAndUseNullHints(TypeBinding type, long nullHints, LookupEnvironment environment) {
@@ -259,6 +265,8 @@
while(it.hasNext())
nullHints |= it.next().nullHints;
}
+ if (nullHints == TagBits.AnnotationNullMASK) // on contradiction remove null type annotations
+ return type.unannotated();
AnnotationBinding[] annot = environment.nullAnnotationsFromTagBits(nullHints);
if (annot != null)
// only get here if exactly one of @NonNull or @Nullable was hinted; now apply this hint:
@@ -306,7 +314,7 @@
for (int i = 0; i < length; i++) {
TypeVariableBinding typeParameter = typeParameters[i];
InferenceVariable variable = variables[i];
- TypeBound[] someBounds = typeParameter.getTypeBounds(variable, context);
+ TypeBound[] someBounds = typeParameter.getTypeBounds(variable, new InferenceSubstitution(context.environment, context.inferenceVariables));
boolean hasProperBound = false;
if (someBounds.length > 0)
hasProperBound = addBounds(someBounds, context.environment);
@@ -503,12 +511,21 @@
ParameterizedTypeBinding gAlpha = capt.getKey();
ParameterizedTypeBinding gA = capt.getValue();
ReferenceBinding g = (ReferenceBinding) gA.original();
- TypeVariableBinding[] parameters = g.typeVariables();
+ final TypeVariableBinding[] parameters = g.typeVariables();
+ // construct theta = [P1:=alpha1,...]
+ final InferenceVariable[] alphas = new InferenceVariable[gAlpha.arguments.length];
+ System.arraycopy(gAlpha.arguments, 0, alphas, 0, alphas.length);
+ InferenceSubstitution theta = new InferenceSubstitution(context.environment, alphas) {
+ @Override
+ protected TypeBinding getP(int i) {
+ return parameters[i];
+ }
+ };
for (int i = 0; i < parameters.length; i++) {
// A set of bounds on α1, ..., αn, constructed from the declared bounds of P1, ..., Pn as described in 18.1.3, is immediately implied.
TypeVariableBinding pi = parameters[i];
InferenceVariable alpha = (InferenceVariable) gAlpha.arguments[i];
- addBounds(pi.getTypeBounds(alpha, context), context.environment);
+ addBounds(pi.getTypeBounds(alpha, theta), context.environment);
TypeBinding ai = gA.arguments[i];
if (ai instanceof WildcardBinding) {
@@ -546,7 +563,7 @@
System.arraycopy(otherBounds, 0, allBounds, 1, n-1);
bi = new IntersectionCastTypeBinding(allBounds, context.environment);
}
- addTypeBoundsFromWildcardBound(context, wildcardBinding.boundKind, t, r, bi);
+ addTypeBoundsFromWildcardBound(context, theta, wildcardBinding.boundKind, t, r, bi);
// if (otherBounds != null) {
// for (int j = 0; j < otherBounds.length; j++) {
// TypeBinding tj = otherBounds[j];
@@ -582,16 +599,16 @@
return true;
}
- void addTypeBoundsFromWildcardBound(InferenceContext18 context, int boundKind, TypeBinding t,
+ void addTypeBoundsFromWildcardBound(InferenceContext18 context, InferenceSubstitution theta, int boundKind, TypeBinding t,
TypeBinding r, TypeBinding bi) throws InferenceFailureException {
ConstraintFormula formula = null;
if (boundKind == Wildcard.EXTENDS) {
if (bi.id == TypeIds.T_JavaLangObject)
formula = ConstraintTypeFormula.create(t, r, ReductionResult.SUBTYPE);
if (t.id == TypeIds.T_JavaLangObject)
- formula = ConstraintTypeFormula.create(context.substitute(bi), r, ReductionResult.SUBTYPE);
+ formula = ConstraintTypeFormula.create(theta.substitute(theta, bi), r, ReductionResult.SUBTYPE);
} else {
- formula = ConstraintTypeFormula.create(context.substitute(bi), r, ReductionResult.SUBTYPE);
+ formula = ConstraintTypeFormula.create(theta.substitute(theta, bi), r, ReductionResult.SUBTYPE);
}
if (formula != null)
reduceOneConstraint(context, formula);
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 5544fe9..840eb82 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
@@ -290,18 +290,25 @@
StringBuffer nameBuffer = new StringBuffer(10);
appendNullAnnotation(nameBuffer, options);
nameBuffer.append(this.sourceName());
- if (this.wildcard != null) {
- nameBuffer.append("of "); //$NON-NLS-1$
- nameBuffer.append(this.wildcard.nullAnnotatedReadableName(options, shortNames));
- } else if (this.lowerBound != null) {
- nameBuffer.append(" super "); //$NON-NLS-1$
- nameBuffer.append(this.lowerBound.nullAnnotatedReadableName(options, shortNames));
- } else if (this.firstBound != null) {
- nameBuffer.append(" extends "); //$NON-NLS-1$
- nameBuffer.append(this.firstBound.nullAnnotatedReadableName(options, shortNames));
- TypeBinding[] otherUpperBounds = this.otherUpperBounds();
- if (otherUpperBounds != NO_TYPES)
- nameBuffer.append(" & ..."); //$NON-NLS-1$ // only hint at more bounds, we currently don't evaluate null annotations on otherUpperBounds
+ if (!this.inRecursiveFunction) { // CaptureBinding18 can be recursive indeed
+ this.inRecursiveFunction = true;
+ try {
+ if (this.wildcard != null) {
+ nameBuffer.append("of "); //$NON-NLS-1$
+ nameBuffer.append(this.wildcard.nullAnnotatedReadableName(options, shortNames));
+ } else if (this.lowerBound != null) {
+ nameBuffer.append(" super "); //$NON-NLS-1$
+ nameBuffer.append(this.lowerBound.nullAnnotatedReadableName(options, shortNames));
+ } else if (this.firstBound != null) {
+ nameBuffer.append(" extends "); //$NON-NLS-1$
+ nameBuffer.append(this.firstBound.nullAnnotatedReadableName(options, shortNames));
+ TypeBinding[] otherUpperBounds = this.otherUpperBounds();
+ if (otherUpperBounds != NO_TYPES)
+ nameBuffer.append(" & ..."); //$NON-NLS-1$ // only hint at more bounds, we currently don't evaluate null annotations on otherUpperBounds
+ }
+ } finally {
+ this.inRecursiveFunction = false;
+ }
}
int nameLength = nameBuffer.length();
char[] readableName = new char[nameLength];
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding18.java
index fa98e4d..4dbff1e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding18.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding18.java
@@ -30,25 +30,15 @@
if (upperBounds.length > 0)
this.firstBound = upperBounds[0];
int numReferenceInterfaces = 0;
+ if (!isConsistentIntersection(upperBounds))
+ return false;
for (int i = 0; i < upperBounds.length; i++) {
TypeBinding aBound = upperBounds[i];
- if (!aBound.isWildcard() && !aBound.isTypeVariable() && aBound.isProperType(true)) {
- // check for inconsistency between any two real types:
- for (int j = 0; j < upperBounds.length; j++) {
- if (i == j) continue;
- TypeBinding otherBound = upperBounds[j];
- if (!otherBound.isWildcard() && !otherBound.isTypeVariable() && otherBound.isProperType(true))
- if (aBound.erasure().isCompatibleWith(otherBound.erasure()))
- if (!aBound.isCompatibleWith(otherBound))
- return false;
- }
- }
if (aBound instanceof ReferenceBinding) {
if (this.superclass == null && aBound.isClass())
- this.superclass = (ReferenceBinding) upperBounds[i];
+ this.superclass = (ReferenceBinding) aBound;
else if (aBound.isInterface())
numReferenceInterfaces++;
- // TODO: what about additional super classes?? (see isCompatibleWith)
}
}
this.superInterfaces = new ReferenceBinding[numReferenceInterfaces];
@@ -80,9 +70,16 @@
public TypeBinding erasure() {
if (this.upperBounds != null && this.upperBounds.length > 1) {
ReferenceBinding[] erasures = new ReferenceBinding[this.upperBounds.length];
+ boolean multipleErasures = false;
for (int i = 0; i < this.upperBounds.length; i++) {
erasures[i] = (ReferenceBinding) this.upperBounds[i].erasure(); // FIXME cast?
+ if (i > 0) {
+ if (TypeBinding.notEquals(erasures[0], erasures[i]))
+ multipleErasures = true;
+ }
}
+ if (!multipleErasures)
+ return erasures[0];
return new IntersectionCastTypeBinding(erasures, this.environment);
}
return super.erasure();
@@ -120,13 +117,20 @@
}
public boolean isCompatibleWith(TypeBinding otherType, Scope captureScope) {
- if (this.upperBounds != null) {
- for (int i = 0; i < this.upperBounds.length; i++) {
- if (this.upperBounds[i].isCompatibleWith(otherType, captureScope))
- return true;
+ if (this.inRecursiveFunction)
+ return true;
+ this.inRecursiveFunction = true;
+ try {
+ if (this.upperBounds != null) {
+ for (int i = 0; i < this.upperBounds.length; i++) {
+ if (this.upperBounds[i].isCompatibleWith(otherType, captureScope))
+ return true;
+ }
}
+ return super.isCompatibleWith(otherType, captureScope);
+ } finally {
+ this.inRecursiveFunction = false;
}
- return super.isCompatibleWith(otherType, captureScope);
}
public TypeBinding findSuperTypeOriginatingFrom(TypeBinding otherType) {
@@ -189,11 +193,25 @@
}
}
if (haveSubstitution) {
- CaptureBinding18 newCapture = (CaptureBinding18) clone(enclosingType());
- newCapture.superclass = currentSuperclass;
- newCapture.superInterfaces = currentSuperInterfaces;
- newCapture.upperBounds = currentUpperBounds;
+ final CaptureBinding18 newCapture = (CaptureBinding18) clone(enclosingType());
newCapture.tagBits = this.tagBits;
+ Substitution substitution = new Substitution() {
+ @Override
+ public TypeBinding substitute(TypeVariableBinding typeVariable) {
+ return (typeVariable == CaptureBinding18.this) ? newCapture : typeVariable; //$IDENTITY-COMPARISON$
+ }
+ @Override
+ public boolean isRawSubstitution() {
+ return false;
+ }
+ @Override
+ public LookupEnvironment environment() {
+ return CaptureBinding18.this.environment;
+ }
+ };
+ newCapture.superclass = (ReferenceBinding) Scope.substitute(substitution, currentSuperclass);
+ newCapture.superInterfaces = Scope.substitute(substitution, currentSuperInterfaces);
+ newCapture.upperBounds = Scope.substitute(substitution, currentUpperBounds);
return newCapture;
}
return this;
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 0166b68..d2fcea1 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, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -17,11 +17,14 @@
* 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
* Bug 427199 - [1.8][resource] avoid resource leak warnings on Streams that have no resource
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
+ * Bug 434570 - Generic type mismatch for parametrized class annotation attribute with inner class
* 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;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -46,7 +49,8 @@
public TypeDeclaration referenceContext;
public TypeReference superTypeReference;
- java.util.ArrayList deferredBoundChecks;
+ java.util.ArrayList<Object> deferredBoundChecks; // contains TypeReference or Runnable. TODO consider making this a List<Runnable>
+ boolean connectingHierarchy;
public ClassScope(Scope parent, TypeDeclaration context) {
super(Scope.CLASS_SCOPE, parent);
@@ -927,8 +931,11 @@
// Perform deferred bound checks for parameterized type references (only done after hierarchy is connected)
public void checkParameterizedTypeBounds() {
- for (int i = 0, l = this.deferredBoundChecks == null ? 0 : this.deferredBoundChecks.size(); i < l; i++)
- ((TypeReference) this.deferredBoundChecks.get(i)).checkBounds(this);
+ for (int i = 0, l = this.deferredBoundChecks == null ? 0 : this.deferredBoundChecks.size(); i < l; i++) {
+ Object toCheck = this.deferredBoundChecks.get(i);
+ if (toCheck instanceof TypeReference)
+ ((TypeReference) toCheck).checkBounds(this);
+ }
this.deferredBoundChecks = null;
ReferenceBinding[] memberTypes = this.referenceContext.binding.memberTypes;
@@ -1128,17 +1135,24 @@
void connectTypeHierarchy() {
SourceTypeBinding sourceType = this.referenceContext.binding;
- if ((sourceType.tagBits & TagBits.BeginHierarchyCheck) == 0) {
- sourceType.tagBits |= TagBits.BeginHierarchyCheck;
- environment().typesBeingConnected.add(sourceType);
- boolean noProblems = connectSuperclass();
- noProblems &= connectSuperInterfaces();
- environment().typesBeingConnected.remove(sourceType);
- sourceType.tagBits |= TagBits.EndHierarchyCheck;
- noProblems &= connectTypeVariables(this.referenceContext.typeParameters, false);
- sourceType.tagBits |= TagBits.TypeVariablesAreConnected;
- if (noProblems && sourceType.isHierarchyInconsistent())
- problemReporter().hierarchyHasProblems(sourceType);
+ try {
+ if ((sourceType.tagBits & TagBits.BeginHierarchyCheck) == 0) {
+ this.connectingHierarchy = true;
+ sourceType.tagBits |= TagBits.BeginHierarchyCheck;
+ environment().typesBeingConnected.add(sourceType);
+ boolean noProblems = connectSuperclass();
+ noProblems &= connectSuperInterfaces();
+ environment().typesBeingConnected.remove(sourceType);
+ sourceType.tagBits |= TagBits.EndHierarchyCheck;
+ noProblems &= connectTypeVariables(this.referenceContext.typeParameters, false);
+ sourceType.tagBits |= TagBits.TypeVariablesAreConnected;
+ if (noProblems && sourceType.isHierarchyInconsistent())
+ problemReporter().hierarchyHasProblems(sourceType);
+ }
+ connectMemberTypes();
+ } finally {
+ this.connectingHierarchy = false;
+ deferredMemberValueCheck();
}
connectMemberTypes();
LookupEnvironment env = environment();
@@ -1153,6 +1167,31 @@
}
}
+ @Override
+ public boolean deferCheck(Runnable check) {
+ if (this.connectingHierarchy) {
+ if (this.deferredBoundChecks == null)
+ this.deferredBoundChecks = new ArrayList<Object>();
+ this.deferredBoundChecks.add(check);
+ return true;
+ } else {
+ return super.deferCheck(check);
+ }
+ }
+
+ private void deferredMemberValueCheck() {
+ if (this.deferredBoundChecks != null) {
+ Iterator iterator = this.deferredBoundChecks.iterator();
+ while (iterator.hasNext()) {
+ Object check = iterator.next();
+ if (check instanceof Runnable) {
+ ((Runnable)check).run();
+ iterator.remove();
+ }
+ }
+ }
+ }
+
private void connectTypeHierarchyWithoutMembers() {
// must ensure the imports are resolved
if (this.parent instanceof CompilationUnitScope) {
@@ -1349,6 +1388,17 @@
return this.referenceContext;
}
+ @Override
+ public boolean hasDefaultNullnessFor(int location) {
+ SourceTypeBinding binding = this.referenceContext.binding;
+ if (binding != null) {
+ int nullDefault = binding.getNullDefault();
+ if (nullDefault != 0)
+ return (nullDefault & location) != 0;
+ }
+ return this.parent.hasDefaultNullnessFor(location);
+ }
+
public String toString() {
if (this.referenceContext != null)
return "--- Class Scope ---\n\n" //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
index a6d75b2..455f6ed 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CompilationUnitScope.java
@@ -8,6 +8,8 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Erling Ellingsen - patch for bug 125570
+ * Stephan Herrmann - Contribution for
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -41,6 +43,18 @@
private ImportBinding[] tempImports; // to keep a record of resolved imports while traversing all in faultInImports()
+ /**
+ * Flag that should be set during annotation traversal or similar runs
+ * to prevent caching of failures regarding imports of yet to be generated classes.
+ */
+ public boolean suppressImportErrors;
+
+ /**
+ * Skips import caching if unresolved imports were
+ * found last time.
+ */
+ private boolean skipCachingImports;
+
public CompilationUnitScope(CompilationUnitDeclaration unit, LookupEnvironment environment) {
super(COMPILATION_UNIT_SCOPE, null);
this.environment = environment;
@@ -322,7 +336,11 @@
this.topLevelTypes[i].scope.connectTypeHierarchy();
}
void faultInImports() {
- if (this.typeOrPackageCache != null)
+ boolean unresolvedFound = false;
+ // should report unresolved only if we are not suppressing caching of failed resolutions
+ boolean reportUnresolved = !this.suppressImportErrors;
+
+ if (this.typeOrPackageCache != null && !this.skipCachingImports)
return; // can be called when a field constant is resolved before static imports
if (this.referenceContext.imports == null) {
this.typeOrPackageCache = new HashtableOfObject(1);
@@ -393,7 +411,10 @@
if (importBinding.problemId() == ProblemReasons.Ambiguous) {
// keep it unless a duplicate can be found below
} else {
- problemReporter().importProblem(importReference, importBinding);
+ unresolvedFound = true;
+ if (reportUnresolved) {
+ problemReporter().importProblem(importReference, importBinding);
+ }
continue nextImport;
}
}
@@ -430,6 +451,7 @@
if (!binding.onDemand && binding.resolvedImport instanceof ReferenceBinding || binding instanceof ImportConflictBinding)
this.typeOrPackageCache.put(binding.compoundName[binding.compoundName.length - 1], binding);
}
+ this.skipCachingImports = this.suppressImportErrors && unresolvedFound;
}
public void faultInTypes() {
faultInImports();
@@ -957,4 +979,10 @@
}
return this.importPtr;
}
+@Override
+public boolean hasDefaultNullnessFor(int location) {
+ if (this.fPackage != null)
+ return (this.fPackage.defaultNullness & location) != 0;
+ return false;
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java
index 5b92214..0d06e45 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ConstraintTypeFormula.java
@@ -345,6 +345,10 @@
return false; // nothing here means we failed
if (TypeBinding.equalsEquals(ca, cb)) // incl C#RAW vs C#RAW
return true;
+ if (!(cb instanceof ParameterizedTypeBinding)) {
+ // if C is parameterized with its own type variables, there're no more constraints to be created here, otherwise let's fail
+ return isInsignificantParameterized(ca);
+ }
TypeBinding[] bi = ((ParameterizedTypeBinding) cb).arguments;
if (cb.isRawType() || bi == null || bi.length == 0)
return (this.isSoft && InferenceContext18.SIMULATE_BUG_JDK_8026527) ? true : false; // FALSE would conform to the spec
@@ -353,6 +357,20 @@
return true;
}
+ private boolean isInsignificantParameterized(ParameterizedTypeBinding ca) {
+ TypeVariableBinding[] typeVariables = ca.original().typeVariables();
+ TypeBinding[] typeArguments = ca.arguments;
+ if (typeVariables == null || typeArguments == null)
+ return typeVariables == typeArguments;
+ if (typeVariables.length != typeArguments.length)
+ return false;
+ for (int i = 0; i < typeArguments.length; i++) {
+ if (TypeBinding.notEquals(typeVariables[i], typeArguments[i]))
+ return false;
+ }
+ return true;
+ }
+
public boolean applySubstitution(BoundSet solutionSet, InferenceVariable[] variables) {
super.applySubstitution(solutionSet, variables);
for (int i=0; i<variables.length; i++) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ElementValuePair.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ElementValuePair.java
index 5a469d6..dc0b587 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ElementValuePair.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ElementValuePair.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -7,6 +7,8 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -18,6 +20,30 @@
char[] name;
public Object value;
public MethodBinding binding;
+
+ /**
+ * We want to avoid eagerly resolving of all enums that are used in annotations.
+ * This class encapsulates an unresolved enum constant as referenced in an ElementValuePair.
+ * The enum constant will be resolved when asking getValue()
+ */
+ public static class UnresolvedEnumConstant {
+ ReferenceBinding enumType;
+ LookupEnvironment environment;
+ char[] enumConstantName;
+ UnresolvedEnumConstant(ReferenceBinding enumType, LookupEnvironment environment, char[] enumConstantName) {
+ this.enumType = enumType;
+ this.environment = environment;
+ this.enumConstantName = enumConstantName;
+ }
+ FieldBinding getResolved() {
+ if (this.enumType.isUnresolvedType())
+ this.enumType = (ReferenceBinding) BinaryTypeBinding.resolveType(this.enumType, this.environment, false /* no raw conversion */);
+ return this.enumType.getField(this.enumConstantName, false);
+ }
+ public char[] getEnumConstantName() {
+ return this.enumConstantName;
+ }
+ }
public static Object getValue(Expression expression) {
if (expression == null)
@@ -88,6 +114,16 @@
* @return the value of this member value pair or null if the value is missing or is not a compile-time constant
*/
public Object getValue() {
+ if (this.value instanceof UnresolvedEnumConstant)
+ this.value = ((UnresolvedEnumConstant)this.value).getResolved();
+ else if (this.value instanceof Object[]) {
+ Object[] valueArray = (Object[]) this.value;
+ for(int i = 0; i < valueArray.length; i++) {
+ Object object = valueArray[i];
+ if (object instanceof UnresolvedEnumConstant)
+ valueArray[i] = ((UnresolvedEnumConstant) object).getResolved();
+ }
+ }
return this.value;
}
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 3485621..0355a83 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
@@ -74,7 +74,9 @@
if (currentType.id == TypeIds.T_JavaLangObject) {
return;
}
- boolean needToApplyNonNullDefault = currentMethod.hasNonNullDefault();
+ long sourceLevel = scope.compilerOptions().sourceLevel;
+ boolean needToApplyNonNullDefault = currentMethod.hasNonNullDefaultFor(Binding.DefaultLocationParameter|Binding.DefaultLocationReturnType,
+ sourceLevel >= ClassFileConstants.JDK1_8);
// compatibility & inheritance do not consider constructors / static methods:
boolean isInstanceMethod = !currentMethod.isConstructor() && !currentMethod.isStatic();
complain &= isInstanceMethod;
@@ -110,7 +112,6 @@
checkNullSpecInheritance(currentMethod, srcMethod, needToApplyNonNullDefault, complain, currentSuper, scope, inheritedNonNullnessInfos);
needToApplyNonNullDefault = false;
}
- long sourceLevel = scope.compilerOptions().sourceLevel;
// transfer collected information into currentMethod:
InheritedNonNullnessInfo info = inheritedNonNullnessInfos[0];
@@ -166,7 +167,10 @@
return;
// superclass:
- collectOverriddenMethods(original, selector, suggestedParameterLength, currentType.superclass(), ifcsSeen, result);
+ ReferenceBinding superclass = currentType.superclass();
+ if (superclass == null)
+ return; // pseudo root of inheritance, happens in eval contexts
+ collectOverriddenMethods(original, selector, suggestedParameterLength, superclass, ifcsSeen, result);
// superInterfaces:
ReferenceBinding[] superInterfaces = currentType.superInterfaces();
@@ -277,7 +281,13 @@
}
}
if (useTypeAnnotations) {
- if (NullAnnotationMatching.analyse(inheritedMethod.returnType, currentMethod.returnType, 0, true).isAnyMismatch()) {
+ TypeBinding substituteReturnType = null; // for TVB identity checks inside NullAnnotationMatching.analyze()
+ TypeVariableBinding[] typeVariables = inheritedMethod.typeVariables;
+ if (typeVariables != null && currentMethod.returnType.id != TypeIds.T_void) {
+ ParameterizedGenericMethodBinding substitute = this.environment.createParameterizedGenericMethod(currentMethod, typeVariables);
+ substituteReturnType = substitute.returnType;
+ }
+ if (NullAnnotationMatching.analyse(inheritedMethod.returnType, currentMethod.returnType, substituteReturnType, 0, true).isAnyMismatch()) {
scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, useTypeAnnotations);
return;
}
@@ -286,6 +296,15 @@
}
// parameters:
+ TypeBinding[] substituteParameters = null; // for TVB identity checks inside NullAnnotationMatching.analyze()
+ if (shouldComplain) {
+ TypeVariableBinding[] typeVariables = currentMethod.typeVariables;
+ if (typeVariables != Binding.NO_TYPE_VARIABLES) {
+ ParameterizedGenericMethodBinding substitute = this.environment.createParameterizedGenericMethod(inheritedMethod, typeVariables);
+ substituteParameters = substitute.parameters;
+ }
+ }
+
Argument[] currentArguments = srcMethod == null ? null : srcMethod.arguments;
int length = 0;
@@ -384,7 +403,8 @@
}
}
if (useTypeAnnotations) {
- if (NullAnnotationMatching.analyse(currentMethod.parameters[i], inheritedMethod.parameters[i], 0, true).isAnyMismatch()) {
+ TypeBinding substituteParameter = substituteParameters != null ? substituteParameters[i] : null;
+ if (NullAnnotationMatching.analyse(currentMethod.parameters[i], inheritedMethod.parameters[i], substituteParameter, 0, true).isAnyMismatch()) {
scope.problemReporter().cannotImplementIncompatibleNullness(currentMethod, inheritedMethod, false);
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
index a517e33..2e6f8aa 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceContext18.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013, 2014 GK Software AG.
+ * Copyright (c) 2013, 2014 GK Software AG, 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
@@ -7,6 +7,7 @@
*
* Contributors:
* Stephan Herrmann - initial API and implementation
+ * IBM Corporation - Bug fixes
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -58,7 +59,7 @@
* replace occurrences of an inference variable with a proper type.</li>
* <li>{@link TypeBinding#collectInferenceVariables(Set)}:
* collect all inference variables mentioned in the receiver type into the given set.</li>
- * <li>{@link TypeVariableBinding#getTypeBounds(InferenceVariable, InferenceContext18)}:
+ * <li>{@link TypeVariableBinding#getTypeBounds(InferenceVariable, InferenceSubstitution)}:
* Compute the initial type bounds for one inference variable as per JLS8 sect 18.1.3.</li>
* </ul>
* <h2>Phases of Inference</h2>
@@ -928,7 +929,7 @@
final int numVars = variableSet.size();
if (numVars > 0) {
final InferenceVariable[] variables = variableSet.toArray(new InferenceVariable[numVars]);
- if (!tmpBoundSet.hasCaptureBound(variableSet)) {
+ variables: if (!tmpBoundSet.hasCaptureBound(variableSet)) {
// try to instantiate this set of variables in a fresh copy of the bound set:
BoundSet prevBoundSet = tmpBoundSet;
tmpBoundSet = tmpBoundSet.copy();
@@ -955,12 +956,18 @@
glb = upperBounds[0];
} else {
ReferenceBinding[] glbs = Scope.greaterLowerBound((ReferenceBinding[])upperBounds);
- if (glbs == null)
+ if (glbs == null) {
throw new UnsupportedOperationException("no glb for "+Arrays.asList(upperBounds)); //$NON-NLS-1$
- else if (glbs.length == 1)
+ } else if (glbs.length == 1) {
glb = glbs[0];
- else
- glb = new IntersectionCastTypeBinding(glbs, this.environment);
+ } else {
+ IntersectionCastTypeBinding intersection = new IntersectionCastTypeBinding(glbs, this.environment);
+ if (!ReferenceBinding.isConsistentIntersection(intersection.intersectingTypes)) {
+ tmpBoundSet = prevBoundSet; // clean up
+ break variables; // and start over
+ }
+ glb = intersection;
+ }
}
}
tmpBoundSet.addBound(new TypeBound(variable, glb, ReductionResult.SAME), this.environment);
@@ -1492,6 +1499,8 @@
ASTNode.resolvePolyExpressionArguments(invocation, innerBinding, this.scope);
}
}
+ } else if(method instanceof ParameterizedMethodBinding){
+ expression.checkAgainstFinalTargetType(targetType, this.scope);
}
} else {
expression.setExpectedType(targetType);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java
index 231a2c2..a4248eb 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/InferenceSubstitution.java
@@ -30,7 +30,7 @@
public TypeBinding substitute(Substitution substitution, TypeBinding originalType) {
for (int i = 0; i < this.variables.length; i++) {
InferenceVariable variable = this.variables[i];
- if (TypeBinding.equalsEquals(variable.typeParameter, originalType)) {
+ if (TypeBinding.equalsEquals(getP(i), originalType)) {
variable.nullHints |= originalType.tagBits & TagBits.AnnotationNullMASK;
return variable;
}
@@ -39,15 +39,25 @@
return super.substitute(substitution, originalType);
}
+ /**
+ * Get the type corresponding to the ith inference variable.
+ * Default behavior is to answer the inference variable's type parameter.
+ * Sub-class may override to substitute other types.
+ */
+ protected TypeBinding getP(int i) {
+ return this.variables[i].typeParameter;
+ }
+
public TypeBinding substitute(TypeVariableBinding typeVariable) {
ReferenceBinding superclass = typeVariable.superclass;
ReferenceBinding[] superInterfaces = typeVariable.superInterfaces;
boolean hasSubstituted = false;
variableLoop: for (int i = 0; i < this.variables.length; i++) {
InferenceVariable variable = this.variables[i];
- if (TypeBinding.equalsEquals(variable.typeParameter, typeVariable))
+ TypeBinding pi = getP(i);
+ if (TypeBinding.equalsEquals(pi, typeVariable))
return variable;
- if (TypeBinding.equalsEquals(variable.typeParameter, superclass)) {
+ if (TypeBinding.equalsEquals(pi, superclass)) {
superclass = variable;
hasSubstituted = true;
continue;
@@ -55,7 +65,7 @@
if (superInterfaces != null) {
int ifcLen = superInterfaces.length;
for (int j = 0; j < ifcLen; j++) {
- if (TypeBinding.equalsEquals(variable.typeParameter, superInterfaces[j])) {
+ if (TypeBinding.equalsEquals(pi, superInterfaces[j])) {
if (superInterfaces == typeVariable.superInterfaces)
System.arraycopy(superInterfaces, 0, superInterfaces = new ReferenceBinding[ifcLen], 0, ifcLen);
superInterfaces[j] = variable;
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 99aecb7..7633473 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -9,7 +9,8 @@
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contributions for
* bug 365662 - [compiler][null] warn on contradictory and redundant null annotations
- * bug 401030 - [1.8][null] Null analysis support for lambda methods.
+ * bug 401030 - [1.8][null] Null analysis support for lambda methods.
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -99,18 +100,23 @@
return this.superclass; // default answer
}
-protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation[] annotations, long annotationTagBits) {
+protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation[] annotations, long nullBits, boolean isJdk18) {
if (!isPrototype()) throw new IllegalStateException();
- long outerDefault = this.enclosingMethod != null ? this.enclosingMethod.tagBits & ((TagBits.AnnotationNonNullByDefault|TagBits.AnnotationNullUnspecifiedByDefault)) : 0;
+ long outerDefault = 0;
+ if (this.enclosingMethod != null) {
+ outerDefault = isJdk18
+ ? this.enclosingMethod.defaultNullness
+ : this.enclosingMethod.tagBits & (TagBits.AnnotationNonNullByDefault|TagBits.AnnotationNullUnspecifiedByDefault);
+ }
if (outerDefault != 0) {
- if (outerDefault == annotationTagBits) {
+ if (outerDefault == nullBits) {
this.scope.problemReporter().nullDefaultAnnotationIsRedundant(location, annotations, this.enclosingMethod);
}
return;
}
- super.checkRedundantNullnessDefaultRecurse(location, annotations, annotationTagBits);
+ super.checkRedundantNullnessDefaultRecurse(location, annotations, nullBits, isJdk18);
}
public char[] computeUniqueKey(boolean isLeaf) {
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 472e746..3fe42fc 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
@@ -19,6 +19,7 @@
* Bug 400874 - [1.8][compiler] Inference infrastructure should evolve to meet JLS8 18.x (Part G of JSR335 spec)
* Bug 425152 - [1.8] [compiler] Lambda Expression not resolved but flow analyzed leading to NPE.
* Bug 423505 - [1.8] Implement "18.5.4 More Specific Method Inference"
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
* Jesper Steen Moller - Contributions for
* Bug 412150 [1.8] [compiler] Enable reflected parameter names during annotation processing
*******************************************************************************/
@@ -35,6 +36,7 @@
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.util.Util;
@SuppressWarnings("rawtypes")
@@ -53,6 +55,7 @@
/** Store nullness information from annotation (incl. applicable default). */
public Boolean[] parameterNonNullness; // TRUE means @NonNull declared, FALSE means @Nullable declared, null means nothing declared
+ public int defaultNullness; // for null *type* annotations
/** Store parameter names from MethodParameters attribute (incl. applicable default). */
public char[][] parameterNames = Binding.NO_PARAMETER_NAMES;
@@ -554,28 +557,31 @@
}
}
+//pre: null annotation analysis is enabled
protected void fillInDefaultNonNullness18(AbstractMethodDeclaration sourceMethod, LookupEnvironment env) {
- boolean added = false;
- int length = this.parameters.length;
- for (int i = 0; i < length; i++) {
- TypeBinding parameter = this.parameters[i];
- if (parameter.isBaseType())
- continue;
- long existing = parameter.tagBits & TagBits.AnnotationNullMASK;
- if (existing == 0L) {
- added = true;
- if (!parameter.isBaseType()) {
- this.parameters[i] = env.createAnnotatedType(parameter, new AnnotationBinding[]{env.getNonNullAnnotation()});
- if (sourceMethod != null)
- sourceMethod.arguments[i].binding.type = this.parameters[i];
+ if (hasNonNullDefaultFor(DefaultLocationParameter, true)) {
+ boolean added = false;
+ int length = this.parameters.length;
+ for (int i = 0; i < length; i++) {
+ TypeBinding parameter = this.parameters[i];
+ if (parameter.isBaseType())
+ continue;
+ long existing = parameter.tagBits & TagBits.AnnotationNullMASK;
+ if (existing == 0L) {
+ added = true;
+ if (!parameter.isBaseType()) {
+ this.parameters[i] = env.createAnnotatedType(parameter, new AnnotationBinding[]{env.getNonNullAnnotation()});
+ if (sourceMethod != null)
+ sourceMethod.arguments[i].binding.type = this.parameters[i];
+ }
+ } else if (sourceMethod != null && (parameter.tagBits & TagBits.AnnotationNonNull) != 0) {
+ sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, i);
}
- } else if (sourceMethod != null && (parameter.tagBits & TagBits.AnnotationNonNull) != 0) {
- sourceMethod.scope.problemReporter().nullAnnotationIsRedundant(sourceMethod, i);
}
+ if (added)
+ this.tagBits |= TagBits.HasParameterAnnotations;
}
- if (added)
- this.tagBits |= TagBits.HasParameterAnnotations;
- if (this.returnType != null) {
+ if (this.returnType != null && hasNonNullDefaultFor(DefaultLocationReturnType, true)) {
if (!this.returnType.isBaseType() && (this.returnType.tagBits & TagBits.AnnotationNullMASK) == 0) {
this.returnType = env.createAnnotatedType(this.returnType, new AnnotationBinding[]{env.getNonNullAnnotation()});
} else if (sourceMethod != null && (this.returnType.tagBits & TagBits.AnnotationNonNull) != 0) {
@@ -669,11 +675,16 @@
AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(originalMethod);
if (methodDecl != null)
ASTNode.resolveAnnotations(methodDecl.scope, methodDecl.annotations, originalMethod);
- long nullDefaultBits = this.tagBits & (TagBits.AnnotationNonNullByDefault|TagBits.AnnotationNullUnspecifiedByDefault);
- if (nullDefaultBits != 0 && this.declaringClass instanceof SourceTypeBinding) {
- SourceTypeBinding declaringSourceType = (SourceTypeBinding) this.declaringClass;
- if (declaringSourceType.checkRedundantNullnessDefaultOne(methodDecl, methodDecl.annotations, nullDefaultBits)) {
- declaringSourceType.checkRedundantNullnessDefaultRecurse(methodDecl, methodDecl.annotations, nullDefaultBits);
+ CompilerOptions options = scope.compilerOptions();
+ if (options.isAnnotationBasedNullAnalysisEnabled) {
+ boolean isJdk18 = options.sourceLevel >= ClassFileConstants.JDK1_8;
+ long nullDefaultBits = isJdk18 ? this.defaultNullness
+ : this.tagBits & (TagBits.AnnotationNonNullByDefault|TagBits.AnnotationNullUnspecifiedByDefault);
+ if (nullDefaultBits != 0 && this.declaringClass instanceof SourceTypeBinding) {
+ SourceTypeBinding declaringSourceType = (SourceTypeBinding) this.declaringClass;
+ if (declaringSourceType.checkRedundantNullnessDefaultOne(methodDecl, methodDecl.annotations, nullDefaultBits, isJdk18)) {
+ declaringSourceType.checkRedundantNullnessDefaultRecurse(methodDecl, methodDecl.annotations, nullDefaultBits, isJdk18);
+ }
}
}
}
@@ -1321,12 +1332,18 @@
public TypeVariableBinding[] typeVariables() {
return this.typeVariables;
}
-public boolean hasNonNullDefault() {
- if ((this.tagBits & TagBits.AnnotationNonNullByDefault) != 0)
- return true;
- if ((this.tagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0)
- return false;
- return this.declaringClass.hasNonNullDefault();
+//pre: null annotation analysis is enabled
+public boolean hasNonNullDefaultFor(int location, boolean useTypeAnnotations) {
+ if (useTypeAnnotations) {
+ if (this.defaultNullness != 0)
+ return (this.defaultNullness & location) != 0;
+ } else {
+ if ((this.tagBits & TagBits.AnnotationNonNullByDefault) != 0)
+ return true;
+ if ((this.tagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0)
+ return false;
+ }
+ return this.declaringClass.hasNonNullDefaultFor(location, useTypeAnnotations);
}
public boolean redeclaresPublicObjectMethod(Scope scope) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
index bb6f059..cf030e5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
@@ -14,6 +14,7 @@
* bug 382354 - [1.8][compiler] Compiler silent on conflicting modifier
* bug 401030 - [1.8][null] Null analysis support for lambda methods.
* Bug 416176 - [1.8][compiler][null] null type annotations cause grief on type variables
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
* Jesper S Moller - Contributions for
* bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
*******************************************************************************/
@@ -54,9 +55,6 @@
public long[] definiteInits = new long[4];
public long[][] extraDefiniteInits = new long[4][];
- // annotation support
- public boolean insideTypeAnnotation = false;
-
// inner-emulation
public SyntheticArgumentBinding[] extraSyntheticArguments;
@@ -564,4 +562,13 @@
void resolveTypeParameter(TypeParameter typeParameter) {
typeParameter.resolve(this);
}
+@Override
+public boolean hasDefaultNullnessFor(int location) {
+ if (this.referenceContext instanceof AbstractMethodDeclaration) {
+ MethodBinding binding = ((AbstractMethodDeclaration) this.referenceContext).binding;
+ if (binding != null && binding.defaultNullness != 0)
+ return (binding.defaultNullness & location) != 0;
+ }
+ return this.parent.hasDefaultNullnessFor(location);
+}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
index 63f4180..b8ee8a8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodVerifier15.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -24,6 +24,8 @@
* Bug 420080 - [1.8] Overridden Default method is reported as duplicated
* Bug 404690 - [1.8][compiler] revisit bridge generation after VM bug is fixed
* Bug 410325 - [1.7][compiler] Generified method override different between javac and eclipse compiler
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
+ * Bug 390889 - [1.8][compiler] Evaluate options to support 1.7- projects against 1.8 JRE.
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -74,7 +76,9 @@
AbstractMethodDeclaration srcMethod = null;
if (analyseNullAnnotations && this.type.equals(concreteMethod.declaringClass)) // is currentMethod from the current type?
srcMethod = concreteMethod.sourceMethod();
- boolean hasNonNullDefault = concreteMethod.hasNonNullDefault();
+ boolean useTypeAnnotations = this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8;
+ boolean hasNonNullDefault = analyseNullAnnotations &&
+ concreteMethod.hasNonNullDefaultFor(Binding.DefaultLocationParameter|Binding.DefaultLocationReturnType, useTypeAnnotations);
for (int i = 0, l = abstractMethods.length; i < l; i++) {
MethodBinding abstractMethod = abstractMethods[i];
if (concreteMethod.isVarargs() != abstractMethod.isVarargs())
@@ -312,7 +316,8 @@
continue;
}
- problemReporter().duplicateInheritedMethods(this.type, concreteMethod, methods[i]);
+ problemReporter().duplicateInheritedMethods(this.type, concreteMethod, methods[i],
+ this.environment.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8);
continueInvestigation = false;
}
concreteMethod = methods[i];
@@ -387,7 +392,8 @@
AbstractMethodDeclaration srcMethod = null;
if (this.type.equals(currentMethod.declaringClass)) // is currentMethod from the current type?
srcMethod = currentMethod.sourceMethod();
- boolean hasNonNullDefault = currentMethod.hasNonNullDefault();
+ boolean useTypeAnnotations = options.sourceLevel >= ClassFileConstants.JDK1_8;
+ boolean hasNonNullDefault = currentMethod.hasNonNullDefaultFor(Binding.DefaultLocationParameter|Binding.DefaultLocationReturnType, useTypeAnnotations);
for (int i = length; --i >= 0;)
if (!currentMethod.isStatic() && !methods[i].isStatic())
checkNullSpecInheritance(currentMethod, srcMethod, hasNonNullDefault, true, methods[i], this.type.scope, null);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MostSpecificExceptionMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MostSpecificExceptionMethodBinding.java
index 37d0536..bfb1f0d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MostSpecificExceptionMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/MostSpecificExceptionMethodBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -7,7 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for bug 186342 - [compiler][null] Using annotations for null checking
+ * Stephan Herrmann - Contributions for
+ * Bug 186342 - [compiler][null] Using annotations for null checking
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -29,6 +31,7 @@
originalMethod.declaringClass);
this.originalMethod = originalMethod;
this.parameterNonNullness = originalMethod.parameterNonNullness;
+ this.defaultNullness = originalMethod.defaultNullness;
}
public MethodBinding original() {
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 9549334..ec4ef6c 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -7,7 +7,9 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Stephan Herrmann - Contribution for bug 365662 - [compiler][null] warn on contradictory and redundant null annotations
+ * Stephan Herrmann - Contributions for
+ * Bug 365662 - [compiler][null] warn on contradictory and redundant null annotations
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
* Keigo Imai - Contribution for bug 388903 - Cannot extend inner class as an anonymous class when it extends the outer class
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -123,16 +125,16 @@
return synthLocal;
}
-protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation[] annotations, long annotationTagBits) {
+protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation[] annotations, long nullBits, boolean isJdk18) {
if (!isPrototype()) throw new IllegalStateException();
ReferenceBinding currentType = this.enclosingType;
do {
- if (!((SourceTypeBinding)currentType).checkRedundantNullnessDefaultOne(location, annotations, annotationTagBits)) {
+ if (!((SourceTypeBinding)currentType).checkRedundantNullnessDefaultOne(location, annotations, nullBits, isJdk18)) {
return;
}
currentType = currentType.enclosingType();
} while (currentType instanceof SourceTypeBinding);
- super.checkRedundantNullnessDefaultRecurse(location, annotations, annotationTagBits);
+ super.checkRedundantNullnessDefaultRecurse(location, annotations, nullBits, isJdk18);
}
/* Answer the receiver's enclosing type... null if the receiver is a top level type.
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 475d906..35f5670 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
@@ -18,6 +18,7 @@
* Bug 427438 - [1.8][compiler] NPE at org.eclipse.jdt.internal.compiler.ast.ConditionalExpression.generateCode(ConditionalExpression.java:280)
* Bug 418743 - [1.8][null] contradictory annotations on invocation of generic method not reported
* Bug 416182 - [1.8][compiler][null] Contradictory null annotations not rejected
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -480,6 +481,7 @@
: Scope.substitute(rawType, originalMethod.returnType));
this.wasInferred = false; // not resulting from method invocation inferrence
this.parameterNonNullness = originalMethod.parameterNonNullness;
+ this.defaultNullness = originalMethod.defaultNullness;
}
/**
@@ -522,6 +524,7 @@
}
this.wasInferred = true;// resulting from method invocation inferrence
this.parameterNonNullness = originalMethod.parameterNonNullness;
+ this.defaultNullness = originalMethod.defaultNullness;
// special case: @NonNull for a parameter that is inferred to 'null' is encoded the old way
// because we cannot (and don't want to) add type annotations to NullTypeBinding.
int len = this.parameters.length;
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 0176185..e7367c0 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
@@ -14,6 +14,7 @@
* 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.
* Bug 425152 - [1.8] [compiler] Lambda Expression not resolved but flow analyzed leading to NPE.
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -48,6 +49,7 @@
*/
this.tagBits = originalMethod.tagBits & ~TagBits.HasMissingType;
this.parameterNonNullness = originalMethod.parameterNonNullness;
+ this.defaultNullness = originalMethod.defaultNullness;
final TypeVariableBinding[] originalVariables = originalMethod.typeVariables;
Substitution substitution = null;
@@ -335,6 +337,7 @@
return this.originalMethod.original();
}
+
public MethodBinding shallowOriginal() {
return this.originalMethod;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PolyTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PolyTypeBinding.java
index e24585c..ff02719 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PolyTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/PolyTypeBinding.java
@@ -14,6 +14,7 @@
package org.eclipse.jdt.internal.compiler.lookup;
import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
public class PolyTypeBinding extends TypeBinding {
@@ -47,7 +48,12 @@
public char[] readableName() {
return this.expression.printExpression(0, new StringBuffer()).toString().toCharArray();
}
-
+
+ public char[] shortReadableName() {
+ return this.expression instanceof LambdaExpression ?
+ ((LambdaExpression) this.expression).printExpression(0, new StringBuffer(), true).toString().toCharArray() : readableName();
+ }
+
public boolean sIsMoreSpecific(TypeBinding s, TypeBinding t, Scope scope) {
return this.expression.sIsMoreSpecific(s, t, scope);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
index 0597a5f..bab0919 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemMethodBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Stephan Herrmann - Contribution for
* Bug 400874 - [1.8][compiler] Inference infrastructure should evolve to meet JLS8 18.x (Part G of JSR335 spec)
+ * Bug 433478 - [compiler][null] NPE in ReferenceBinding.isCompatibleWith
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -34,7 +35,10 @@
public ProblemMethodBinding(MethodBinding closestMatch, char[] selector, TypeBinding[] args, int problemReason) {
this(selector, args, problemReason);
this.closestMatch = closestMatch;
- if (closestMatch != null && problemReason != ProblemReasons.Ambiguous) this.declaringClass = closestMatch.declaringClass;
+ if (closestMatch != null && problemReason != ProblemReasons.Ambiguous) {
+ this.declaringClass = closestMatch.declaringClass;
+ this.returnType = closestMatch.returnType;
+ }
}
/* API
* Answer the problem id associated with the receiver.
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
index e785703..8eb91db 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -91,6 +91,10 @@
return readableName();
}
+public char[] sourceName() {
+ return this.compoundName.length == 0 ? null : this.compoundName[this.compoundName.length - 1]; // last segment of [java][util][Map$Entry]
+}
+
public String toString() {
StringBuffer buffer = new StringBuffer(10);
buffer.append("ProblemType:[compoundName="); //$NON-NLS-1$
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 7798471..10083ec 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
@@ -29,6 +29,8 @@
* Bug 428019 - [1.8][compiler] Type inference failure with nested generic invocation.
* Bug 427199 - [1.8][resource] avoid resource leak warnings on Streams that have no resource
* Bug 418743 - [1.8][null] contradictory annotations on invocation of generic method not reported
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
+ * Bug 431581 - Eclipse compiles what it should not
* 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
@@ -1141,20 +1143,35 @@
}
/**
- * Answer whether a @NonNullByDefault is applicable at the given method binding.
+ * Answer whether a @NonNullByDefault is applicable at the reference binding,
+ * for 1.8 check if the default is applicable to the given kind of location.
*/
-boolean hasNonNullDefault() {
+// pre: null annotation analysis is enabled
+boolean hasNonNullDefaultFor(int location, boolean useTypeAnnotations) {
// Note, STB overrides for correctly handling local types
ReferenceBinding currentType = this;
while (currentType != null) {
- if ((currentType.tagBits & TagBits.AnnotationNonNullByDefault) != 0)
- return true;
- if ((currentType.tagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0)
- return false;
+ if (useTypeAnnotations) {
+ int nullDefault = ((ReferenceBinding)currentType.original()).getNullDefault();
+ if (nullDefault != 0)
+ return (nullDefault & location) != 0;
+ } else {
+ if ((currentType.tagBits & TagBits.AnnotationNonNullByDefault) != 0)
+ return true;
+ if ((currentType.tagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0)
+ return false;
+ }
currentType = currentType.enclosingType();
}
// package
- return this.getPackage().defaultNullness == NONNULL_BY_DEFAULT;
+ if (useTypeAnnotations)
+ return (this.getPackage().defaultNullness & location) != 0;
+ else
+ return this.getPackage().defaultNullness == NONNULL_BY_DEFAULT;
+}
+
+int getNullDefault() {
+ return 0;
}
public final boolean hasRestrictedAccess() {
@@ -1929,48 +1946,29 @@
int contractsCount = 0;
int contractsLength = 0;
- // -- the following are used for early termination.
- MethodBinding aContract = null;
- int contractParameterLength = 0;
- char [] contractSelector = null;
- // ---
-
ReferenceBinding [] superInterfaces = superInterfaces();
for (int i = 0, length = superInterfaces.length; i < length; i++) {
MethodBinding [] superInterfaceContracts = superInterfaces[i].getInterfaceAbstractContracts(scope);
final int superInterfaceContractsLength = superInterfaceContracts == null ? 0 : superInterfaceContracts.length;
-
if (superInterfaceContractsLength == 0) continue;
- if (aContract == null) {
- aContract = superInterfaceContracts[0];
- contractParameterLength = aContract.parameters.length;
- contractSelector = aContract.selector;
- contracts = superInterfaceContracts;
- contractsCount = contractsLength = superInterfaceContractsLength;
- } else {
- if (superInterfaceContracts[0].parameters.length != contractParameterLength || !CharOperation.equals(contractSelector, superInterfaceContracts[0].selector)) {
- throw new InvalidInputException("Not a functional interface"); //$NON-NLS-1$
- }
- if (contractsLength < contractsCount + superInterfaceContractsLength) {
- System.arraycopy(contracts, 0, contracts = new MethodBinding[contractsLength = contractsCount + superInterfaceContractsLength], 0, contractsCount);
- }
- System.arraycopy(superInterfaceContracts, 0, contracts, contractsCount, superInterfaceContractsLength);
- contractsCount += superInterfaceContractsLength;
+ if (contractsLength < contractsCount + superInterfaceContractsLength) {
+ System.arraycopy(contracts, 0, contracts = new MethodBinding[contractsLength = contractsCount + superInterfaceContractsLength], 0, contractsCount);
}
+ System.arraycopy(superInterfaceContracts, 0, contracts, contractsCount, superInterfaceContractsLength);
+ contractsCount += superInterfaceContractsLength;
}
+
for (int i = 0, length = methods == null ? 0 : methods.length; i < length; i++) {
final MethodBinding method = methods[i];
- if (method.isStatic() || method.redeclaresPublicObjectMethod(scope)) continue;
+ if (method == null || method.isStatic() || method.redeclaresPublicObjectMethod(scope))
+ continue;
+ if (!method.isValidBinding())
+ throw new InvalidInputException("Not a functional interface"); //$NON-NLS-1$
if (method.isDefaultMethod()) {
for (int j = 0; j < contractsCount; j++) {
if (contracts[j] == null)
continue;
if (MethodVerifier.doesMethodOverride(method, contracts[j], scope.environment())) {
- if (aContract == contracts[j]) {
- aContract = null;
- contractParameterLength = 0;
- contractSelector = null;
- }
contractsCount--;
// abstract method from super type rendered default by present interface ==> contracts[j] = null;
if (j < contractsCount)
@@ -1979,16 +1977,6 @@
}
continue; // skip default method itself
}
- final boolean validBinding = method.isValidBinding();
- if (aContract == null && validBinding) {
- aContract = method;
- contractParameterLength = aContract.parameters.length;
- contractSelector = aContract.selector;
- } else {
- if (!validBinding || method.parameters.length != contractParameterLength || !CharOperation.equals(contractSelector, method.selector)) {
- throw new InvalidInputException("Not a functional interface"); //$NON-NLS-1$
- }
- }
if (contractsCount == contractsLength) {
System.arraycopy(contracts, 0, contracts = new MethodBinding[contractsLength += 16], 0, contractsCount);
}
@@ -2014,15 +2002,32 @@
MethodBinding[] methods = null;
try {
methods = getInterfaceAbstractContracts(scope);
+ if (methods == null || methods.length == 0)
+ return this.singleAbstractMethod[index] = samProblemBinding;
+ int contractParameterLength = 0;
+ char [] contractSelector = null;
+ for (int i = 0, length = methods.length; i < length; i++) {
+ MethodBinding method = methods[i];
+ if (method == null) continue;
+ if (contractSelector == null) {
+ contractSelector = method.selector;
+ contractParameterLength = method.parameters == null ? 0 : method.parameters.length;
+ } else {
+ int methodParameterLength = method.parameters == null ? 0 : method.parameters.length;
+ if (methodParameterLength != contractParameterLength || !CharOperation.equals(method.selector, contractSelector))
+ return this.singleAbstractMethod[index] = samProblemBinding;
+ }
+ }
} catch (InvalidInputException e) {
return this.singleAbstractMethod[index] = samProblemBinding;
}
- if (methods != null && methods.length == 1)
+ if (methods.length == 1)
return this.singleAbstractMethod[index] = methods[0];
final LookupEnvironment environment = scope.environment();
boolean genericMethodSeen = false;
int length = methods.length;
+
next:for (int i = length - 1; i >= 0; --i) {
MethodBinding method = methods[i], otherMethod = null;
if (method.typeVariables != Binding.NO_TYPE_VARIABLES)
@@ -2114,4 +2119,28 @@
}
return this.singleAbstractMethod[index] = samProblemBinding;
}
+
+// See JLS 4.9 bullet 1
+public static boolean isConsistentIntersection(TypeBinding[] intersectingTypes) {
+ TypeBinding[] ci = new TypeBinding[intersectingTypes.length];
+ for (int i = 0; i < ci.length; i++) {
+ TypeBinding current = intersectingTypes[i];
+ ci[i] = (current.isClass() || current.isArrayType())
+ ? current : current.superclass();
+ }
+ TypeBinding mostSpecific = ci[0];
+ for (int i = 1; i < ci.length; i++) {
+ TypeBinding current = ci[i];
+ // when invoked during type inference we only want to check inconsistency among real types:
+ if (current.isTypeVariable() || current.isWildcard() || !current.isProperType(true))
+ continue;
+ if (mostSpecific.isSubtypeOf(current))
+ continue;
+ else if (current.isSubtypeOf(mostSpecific))
+ mostSpecific = current;
+ else
+ return false;
+ }
+ return true;
+}
}
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 f201ad2..a39a90a 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
@@ -41,6 +41,8 @@
* Bug 424728 - [1.8][null] Unexpected error: The nullness annotation 'XXXX' is not applicable at this location
* Bug 428811 - [1.8][compiler] Type witness unnecessarily required
* Bug 429424 - [1.8][inference] Problem inferring type of method's parameter
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
+ * Bug 434570 - Generic type mismatch for parametrized class annotation attribute with inner class
* Jesper S Moller - Contributions for
* Bug 378674 - "The method can be declared as static" is wrong
* Bug 405066 - [1.8][compiler][codegen] Implement code generation infrastructure for JSR335
@@ -943,8 +945,8 @@
continue nextVariable;
boolean isFirstBoundTypeVariable = false;
TypeBinding superType = this.kind == METHOD_SCOPE
- ? typeRef.resolveType((BlockScope)this, false/*no bound check*/)
- : typeRef.resolveType((ClassScope)this);
+ ? typeRef.resolveType((BlockScope)this, false/*no bound check*/, Binding.DefaultLocationTypeBound)
+ : typeRef.resolveType((ClassScope)this, Binding.DefaultLocationTypeBound);
if (superType == null) {
typeVariable.tagBits |= TagBits.HierarchyHasProblems;
} else {
@@ -5010,6 +5012,12 @@
return null;
}
+ public boolean deferCheck(Runnable check) {
+ if (this.parent != null)
+ return this.parent.deferCheck(check); // only ClassScope potentially records this
+ return false;
+ }
+
public void deferBoundCheck(TypeReference typeRef) {
if (this.kind == CLASS_SCOPE) {
ClassScope classScope = (ClassScope) this;
@@ -5188,6 +5196,10 @@
}
return true;
}
+
+ /** Answer a defaultNullness defined for the closest enclosing scope, using bits from Binding.NullnessDefaultMASK. */
+ public abstract boolean hasDefaultNullnessFor(int location);
+
public static BlockScope typeAnnotationsResolutionScope(Scope scope) {
BlockScope resolutionScope = null;
switch(scope.kind) {
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 411df04..3748521 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
@@ -30,6 +30,8 @@
* Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
* Bug 426048 - [1.8] NPE in TypeVariableBinding.internalBoundCheck when parentheses are not balanced
* Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
+ * Bug 432348 - [1.8] Internal compiler error (NPE) after upgrade to 1.8
* Jesper S Moller <jesper@selskabet.org> - Contributions for
* Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
* Till Brychcy - Contributions for
@@ -104,7 +106,7 @@
private SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder
- private int defaultNullness;
+ public int defaultNullness;
private int nullnessDefaultInitialized = 0; // 0: nothing; 1: type; 2: package
private int lambdaOrdinal = 0;
private ReferenceBinding containerAnnotationType = null;
@@ -1413,7 +1415,7 @@
this.scope.buildMethods();
}
-private int getNullDefault() {
+int getNullDefault() {
if (!isPrototype()) {
return this.prototype.getNullDefault();
@@ -1824,9 +1826,10 @@
if (sourceLevel >= ClassFileConstants.JDK1_8) {
Annotation [] annotations = fieldDecl.annotations;
if (annotations != null && annotations.length != 0) {
- ASTNode.copySE8AnnotationsToType(initializationScope, field, fieldDecl.annotations);
+ ASTNode.copySE8AnnotationsToType(initializationScope, field, annotations,
+ fieldDecl.getKind() != AbstractVariableDeclaration.ENUM_CONSTANT); // type annotation is illegal on enum constant
}
- Annotation.isTypeUseCompatible(fieldDecl.type, this.scope, fieldDecl.annotations);
+ Annotation.isTypeUseCompatible(fieldDecl.type, this.scope, annotations);
}
// apply null default:
if (this.environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
@@ -1835,7 +1838,7 @@
// enum constants neither have a type declaration nor can they be null
field.tagBits |= TagBits.AnnotationNonNull;
} else {
- if (hasNonNullDefault()) {
+ if (hasNonNullDefaultFor(DefaultLocationField, sourceLevel >= ClassFileConstants.JDK1_8)) {
field.fillInDefaultNonNullness(fieldDecl, initializationScope);
}
// validate null annotation:
@@ -2018,7 +2021,7 @@
if (sourceLevel >= ClassFileConstants.JDK1_8 && !method.isVoidMethod()) {
Annotation [] annotations = methodDecl.annotations;
if (annotations != null && annotations.length != 0) {
- ASTNode.copySE8AnnotationsToType(methodDecl.scope, method, methodDecl.annotations);
+ ASTNode.copySE8AnnotationsToType(methodDecl.scope, method, methodDecl.annotations, true);
}
Annotation.isTypeUseCompatible(returnType, this.scope, methodDecl.annotations);
}
@@ -2126,35 +2129,78 @@
}
}
this.nullnessDefaultInitialized = 1;
- // transfer nullness info from tagBits to this.nullnessDefaultAnnotation
- int newDefaultNullness = NO_NULL_DEFAULT;
- if ((annotationTagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0)
- newDefaultNullness = NULL_UNSPECIFIED_BY_DEFAULT;
- else if ((annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0)
- newDefaultNullness = NONNULL_BY_DEFAULT;
- if (newDefaultNullness != NO_NULL_DEFAULT) {
- if (isPackageInfo) {
- pkg.defaultNullness = newDefaultNullness;
- } else {
- this.defaultNullness = newDefaultNullness;
- TypeDeclaration typeDecl = this.scope.referenceContext;
- long nullDefaultBits = annotationTagBits & (TagBits.AnnotationNullUnspecifiedByDefault|TagBits.AnnotationNonNullByDefault);
- checkRedundantNullnessDefaultRecurse(typeDecl, typeDecl.annotations, nullDefaultBits);
+ boolean isJdk18 = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8;
+ if (isJdk18) {
+ if (this.defaultNullness != 0) {
+ if (isPackageInfo) {
+ pkg.defaultNullness = this.defaultNullness;
+ } else {
+ TypeDeclaration typeDecl = this.scope.referenceContext;
+ checkRedundantNullnessDefaultRecurse(typeDecl, typeDecl.annotations, this.defaultNullness, isJdk18);
+ }
+ } else if (isPackageInfo || (isInDefaultPkg && !(this instanceof NestedTypeBinding))) {
+ this.scope.problemReporter().missingNonNullByDefaultAnnotation(this.scope.referenceContext);
+ if (!isInDefaultPkg)
+ pkg.defaultNullness = NULL_UNSPECIFIED_BY_DEFAULT;
}
- } else if (isPackageInfo || (isInDefaultPkg && !(this instanceof NestedTypeBinding))) {
- this.scope.problemReporter().missingNonNullByDefaultAnnotation(this.scope.referenceContext);
- if (!isInDefaultPkg)
- pkg.defaultNullness = NULL_UNSPECIFIED_BY_DEFAULT;
+ } else {
+ // transfer nullness info from tagBits to this.nullnessDefaultAnnotation
+ int newDefaultNullness = NO_NULL_DEFAULT;
+ if ((annotationTagBits & TagBits.AnnotationNullUnspecifiedByDefault) != 0)
+ newDefaultNullness = NULL_UNSPECIFIED_BY_DEFAULT;
+ else if ((annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0)
+ newDefaultNullness = NONNULL_BY_DEFAULT;
+ if (newDefaultNullness != NO_NULL_DEFAULT) {
+ if (isPackageInfo) {
+ pkg.defaultNullness = newDefaultNullness;
+ } else {
+ this.defaultNullness = newDefaultNullness;
+ TypeDeclaration typeDecl = this.scope.referenceContext;
+ long nullDefaultBits = annotationTagBits & (TagBits.AnnotationNullUnspecifiedByDefault|TagBits.AnnotationNonNullByDefault);
+ checkRedundantNullnessDefaultRecurse(typeDecl, typeDecl.annotations, nullDefaultBits, false);
+ }
+ } else if (isPackageInfo || (isInDefaultPkg && !(this instanceof NestedTypeBinding))) {
+ this.scope.problemReporter().missingNonNullByDefaultAnnotation(this.scope.referenceContext);
+ if (!isInDefaultPkg)
+ pkg.defaultNullness = NULL_UNSPECIFIED_BY_DEFAULT;
+ }
+ }
+ maybeMarkTypeParametersNonNull();
+}
+
+private void maybeMarkTypeParametersNonNull() {
+ // when creating type variables we didn't yet have the defaultNullness, fill it in now:
+ if (this.scope == null || !this.scope.hasDefaultNullnessFor(DefaultLocationTypeParameter))
+ return;
+ if (this.typeVariables != null && this.typeVariables.length > 0) {
+ AnnotationBinding[] annots = new AnnotationBinding[]{ this.environment.getNonNullAnnotation() };
+ for (int i = 0; i < this.typeVariables.length; i++) {
+ TypeVariableBinding tvb = this.typeVariables[i];
+ if ((tvb.tagBits & TagBits.AnnotationNullMASK) == 0)
+ this.typeVariables[i] = (TypeVariableBinding) this.environment.createAnnotatedType(tvb, annots);
+ }
}
}
-protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation[] annotations, long annotationTagBits) {
+/**
+ * Recursively check if the given annotations are redundant with equal annotations at an enclosing level.
+ * @param location fallback location to report the warning against (if we can't blame a specific annotation)
+ * @param annotations search these for the annotation that should be blamed in warning messages
+ * @param nullBits in 1.7- times these are the annotationTagBits, in 1.8+ the bitvector from {@link Binding#NullnessDefaultMASK}
+ * @param isJdk18 toggles the interpretation of 'nullBits'
+ *
+ * @pre null annotation analysis is enabled
+ */
+protected void checkRedundantNullnessDefaultRecurse(ASTNode location, Annotation[] annotations, long nullBits, boolean isJdk18) {
if (!isPrototype()) throw new IllegalStateException();
if (this.fPackage.defaultNullness != NO_NULL_DEFAULT) {
- if ((this.fPackage.defaultNullness == NONNULL_BY_DEFAULT
- && ((annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0))) {
+ boolean isRedundant = isJdk18
+ ? this.fPackage.defaultNullness == nullBits
+ : (this.fPackage.defaultNullness == NONNULL_BY_DEFAULT
+ && ((nullBits & TagBits.AnnotationNonNullByDefault) != 0));
+ if (isRedundant) {
this.scope.problemReporter().nullDefaultAnnotationIsRedundant(location, annotations, this.fPackage);
}
return;
@@ -2162,13 +2208,16 @@
}
// return: should caller continue searching?
-protected boolean checkRedundantNullnessDefaultOne(ASTNode location, Annotation[] annotations, long annotationTagBits) {
+protected boolean checkRedundantNullnessDefaultOne(ASTNode location, Annotation[] annotations, long nullBits, boolean isJdk18) {
if (!isPrototype()) throw new IllegalStateException();
int thisDefault = getNullDefault();
- if (thisDefault == NONNULL_BY_DEFAULT) {
- if ((annotationTagBits & TagBits.AnnotationNonNullByDefault) != 0) {
+ if (thisDefault != NO_NULL_DEFAULT) {
+ boolean isRedundant = isJdk18
+ ? thisDefault == nullBits
+ : (nullBits & TagBits.AnnotationNonNullByDefault) != 0;
+ if (isRedundant) {
this.scope.problemReporter().nullDefaultAnnotationIsRedundant(location, annotations, this);
}
return false; // different default means inner default is not redundant -> we're done
@@ -2176,10 +2225,18 @@
return true;
}
-boolean hasNonNullDefault() {
+boolean hasNonNullDefaultFor(int location, boolean useTypeAnnotations) {
if (!isPrototype()) throw new IllegalStateException();
+ // 1.8:
+ if (useTypeAnnotations) {
+ if (this.scope == null) {
+ return (this.defaultNullness & location) != 0;
+ }
+ return this.scope.hasDefaultNullnessFor(location);
+ }
+
// find the applicable default inside->out:
SourceTypeBinding currentType = null;
@@ -2200,6 +2257,9 @@
currentType = ((ClassScope)currentScope).referenceContext.binding;
if (currentType != null) {
int foundDefaultNullness = currentType.getNullDefault();
+ if ((foundDefaultNullness & NullnessDefaultMASK) > NULL_UNSPECIFIED_BY_DEFAULT) {
+ return true;
+ }
if (foundDefaultNullness != NO_NULL_DEFAULT) {
return foundDefaultNullness == NONNULL_BY_DEFAULT;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBound.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBound.java
index 03e57d7..59845e3 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBound.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBound.java
@@ -26,9 +26,9 @@
// here we accumulate null tagBits from any types that have been related to this type bound during incorporation:
long nullHints;
- static TypeBound createBoundOrDependency(InferenceContext18 context, TypeBinding type, InferenceVariable variable) {
+ static TypeBound createBoundOrDependency(InferenceSubstitution theta, TypeBinding type, InferenceVariable variable) {
// Part of JLS8 sect 18.1.3:
- return new TypeBound(variable, context.substitute(type), SUBTYPE, true);
+ return new TypeBound(variable, theta.substitute(theta, type), SUBTYPE, true);
}
/** Create a true type bound or a dependency. */
@@ -47,7 +47,7 @@
private TypeBinding safeType(TypeBinding type) {
if (type != null && type.isLocalType()) {
- MethodBinding enclosingMethod = ((LocalTypeBinding) type).enclosingMethod;
+ MethodBinding enclosingMethod = ((LocalTypeBinding) type.original()).enclosingMethod;
if (enclosingMethod != null && CharOperation.prefixEquals(TypeConstants.ANONYMOUS_METHOD, enclosingMethod.selector))
return type.superclass(); // don't use local class inside lambda: lambda is copied, type will be re-created and thus is unmatchable
}
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 5a238e1..81ba847 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
@@ -16,6 +16,7 @@
* Bug 405569 - Resource leak check false positive when using DbUtils.closeQuietly
* Bug 427199 - [1.8][resource] avoid resource leak warnings on Streams that have no resource
* Bug 425183 - [1.8][inference] make CaptureBinding18 safe
+ * Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
* Jesper S Moller - Contributions for
* 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
@@ -351,6 +352,16 @@
char[] SYNTHETIC_ENUM_CONSTANT_INITIALIZATION_METHOD_PREFIX = " enum constant initialization$".toCharArray(); //$NON-NLS-1$
char[] SYNTHETIC_STATIC_FACTORY = "<factory>".toCharArray(); //$NON-NLS-1$
+ // constants in enum org.eclipse.jdt.annotation.DefaultLocation:
+ char[] DEFAULT_LOCATION__PARAMETER = "PARAMETER".toCharArray(); //$NON-NLS-1$
+ char[] DEFAULT_LOCATION__RETURN_TYPE = "RETURN_TYPE".toCharArray(); //$NON-NLS-1$
+ char[] DEFAULT_LOCATION__FIELD = "FIELD".toCharArray(); //$NON-NLS-1$
+ char[] DEFAULT_LOCATION__TYPE_ARGUMENT = "TYPE_ARGUMENT".toCharArray(); //$NON-NLS-1$
+ char[] DEFAULT_LOCATION__TYPE_PARAMETER = "TYPE_PARAMETER".toCharArray(); //$NON-NLS-1$
+ char[] DEFAULT_LOCATION__TYPE_BOUND = "TYPE_BOUND".toCharArray(); //$NON-NLS-1$
+ char[] DEFAULT_LOCATION__ARRAY_CONTENTS = "ARRAY_CONTENTS".toCharArray(); //$NON-NLS-1$
+
+
// synthetic package-info name
public static final char[] PACKAGE_INFO_NAME = "package-info".toCharArray(); //$NON-NLS-1$
}
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 1757f3c..46dd12d 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,6 +20,8 @@
* Bug 426792 - [1.8][inference][impl] generify new type inference engine
* Bug 428019 - [1.8][compiler] Type inference failure with nested generic invocation.
* Bug 429384 - [1.8][null] implement conformance rules for null-annotated lower / upper type bounds
+ * Bug 431269 - [1.8][compiler][null] StackOverflow in nullAnnotatedReadableName
+ * Bug 431408 - Java 8 (1.8) generics bug
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -314,18 +316,25 @@
public String annotatedDebugName() {
StringBuffer buffer = new StringBuffer(10);
buffer.append(super.annotatedDebugName());
- if (this.superclass != null && TypeBinding.equalsEquals(this.firstBound, this.superclass)) {
- buffer.append(" extends ").append(this.superclass.annotatedDebugName()); //$NON-NLS-1$
- }
- if (this.superInterfaces != null && this.superInterfaces != Binding.NO_SUPERINTERFACES) {
- if (TypeBinding.notEquals(this.firstBound, this.superclass)) {
- buffer.append(" extends "); //$NON-NLS-1$
- }
- for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
- if (i > 0 || TypeBinding.equalsEquals(this.firstBound, this.superclass)) {
- buffer.append(" & "); //$NON-NLS-1$
- }
- buffer.append(this.superInterfaces[i].annotatedDebugName());
+ if (!this.inRecursiveFunction) {
+ this.inRecursiveFunction = true;
+ try {
+ if (this.superclass != null && TypeBinding.equalsEquals(this.firstBound, this.superclass)) {
+ buffer.append(" extends ").append(this.superclass.annotatedDebugName()); //$NON-NLS-1$
+ }
+ if (this.superInterfaces != null && this.superInterfaces != Binding.NO_SUPERINTERFACES) {
+ if (TypeBinding.notEquals(this.firstBound, this.superclass)) {
+ buffer.append(" extends "); //$NON-NLS-1$
+ }
+ for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
+ if (i > 0 || TypeBinding.equalsEquals(this.firstBound, this.superclass)) {
+ buffer.append(" & "); //$NON-NLS-1$
+ }
+ buffer.append(this.superInterfaces[i].annotatedDebugName());
+ }
+ }
+ } finally {
+ this.inRecursiveFunction = false;
}
}
return buffer.toString();
@@ -376,15 +385,15 @@
/**
* Compute the initial type bounds for one inference variable as per JLS8 sect 18.1.3.
*/
- TypeBound[] getTypeBounds(InferenceVariable variable, InferenceContext18 context) {
+ TypeBound[] getTypeBounds(InferenceVariable variable, InferenceSubstitution theta) {
int n = boundsCount();
if (n == 0)
return NO_TYPE_BOUNDS;
TypeBound[] bounds = new TypeBound[n];
- bounds[0] = TypeBound.createBoundOrDependency(context, this.firstBound, variable);
+ bounds[0] = TypeBound.createBoundOrDependency(theta, this.firstBound, variable);
int ifcOffset = TypeBinding.equalsEquals(this.firstBound, this.superclass) ? -1 : 0;
for (int i = 1; i < n; i++)
- bounds[i] = TypeBound.createBoundOrDependency(context, this.superInterfaces[i+ifcOffset], variable);
+ bounds[i] = TypeBound.createBoundOrDependency(theta, this.superInterfaces[i+ifcOffset], variable);
return bounds;
}
@@ -724,18 +733,25 @@
StringBuffer nameBuffer = new StringBuffer(10);
appendNullAnnotation(nameBuffer, options);
nameBuffer.append(this.sourceName());
- if (this.superclass != null && TypeBinding.equalsEquals(this.firstBound, this.superclass)) {
- nameBuffer.append(" extends ").append(this.superclass.nullAnnotatedReadableName(options, shortNames)); //$NON-NLS-1$
- }
- if (this.superInterfaces != null && this.superInterfaces != Binding.NO_SUPERINTERFACES) {
- if (TypeBinding.notEquals(this.firstBound, this.superclass)) {
- nameBuffer.append(" extends "); //$NON-NLS-1$
- }
- for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
- if (i > 0 || TypeBinding.equalsEquals(this.firstBound, this.superclass)) {
- nameBuffer.append(" & "); //$NON-NLS-1$
- }
- nameBuffer.append(this.superInterfaces[i].nullAnnotatedReadableName(options, shortNames));
+ if (!this.inRecursiveFunction) {
+ this.inRecursiveFunction = true;
+ try {
+ if (this.superclass != null && TypeBinding.equalsEquals(this.firstBound, this.superclass)) {
+ nameBuffer.append(" extends ").append(this.superclass.nullAnnotatedReadableName(options, shortNames)); //$NON-NLS-1$
+ }
+ if (this.superInterfaces != null && this.superInterfaces != Binding.NO_SUPERINTERFACES) {
+ if (TypeBinding.notEquals(this.firstBound, this.superclass)) {
+ nameBuffer.append(" extends "); //$NON-NLS-1$
+ }
+ for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
+ if (i > 0 || TypeBinding.equalsEquals(this.firstBound, this.superclass)) {
+ nameBuffer.append(" & "); //$NON-NLS-1$
+ }
+ nameBuffer.append(this.superInterfaces[i].nullAnnotatedReadableName(options, shortNames));
+ }
+ }
+ } finally {
+ this.inRecursiveFunction = false;
}
}
int nameLength = nameBuffer.length();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TheOriginalJDTParserClass.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TheOriginalJDTParserClass.java
index a031304..7469cf1 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TheOriginalJDTParserClass.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TheOriginalJDTParserClass.java
@@ -920,6 +920,7 @@
protected int[] expressionLengthStack;
protected int expressionPtr;
protected Expression[] expressionStack = new Expression[ExpressionStackIncrement];
+ protected int rBracketPosition;
public int firstToken ; // handle for multiple parsing goals
/* jsr308 -- Type annotation management, we now maintain type annotations in a separate stack
@@ -4972,7 +4973,11 @@
md.bodyEnd = this.endPosition;
md.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
if (isDefaultMethod && !this.tolerateDefaultClassMethods) {
- problemReporter().defaultModifierIllegallySpecified(md.bodyStart, this.endPosition);
+ if (this.options.sourceLevel >= ClassFileConstants.JDK1_8) {
+ problemReporter().defaultModifierIllegallySpecified(md.sourceStart, md.sourceEnd);
+ } else {
+ problemReporter().illegalModifierForMethod(md);
+ }
}
}
protected void consumeMethodHeader() {
@@ -6191,6 +6196,7 @@
int sourceEnd;
sourceEnd = (int) this.identifierPositionStack[this.identifierPtr];
+ referenceExpression.nameSourceStart = (int) (this.identifierPositionStack[this.identifierPtr] >>> 32);
selector = this.identifierStack[this.identifierPtr--];
this.identifierLengthPtr--;
@@ -6231,6 +6237,7 @@
int sourceEnd;
sourceEnd = (int) this.identifierPositionStack[this.identifierPtr];
+ referenceExpression.nameSourceStart = (int) (this.identifierPositionStack[this.identifierPtr] >>> 32);
selector = this.identifierStack[this.identifierPtr--];
this.identifierLengthPtr--;
@@ -6255,6 +6262,7 @@
int sourceEnd;
sourceEnd = (int) this.identifierPositionStack[this.identifierPtr];
+ referenceExpression.nameSourceStart = (int) (this.identifierPositionStack[this.identifierPtr] >>> 32);
selector = this.identifierStack[this.identifierPtr--];
this.identifierLengthPtr--;
@@ -6294,6 +6302,7 @@
int sourceEnd;
sourceEnd = (int) this.identifierPositionStack[this.identifierPtr];
+ referenceExpression.nameSourceStart = (int) (this.identifierPositionStack[this.identifierPtr] >>> 32);
selector = this.identifierStack[this.identifierPtr--];
this.identifierLengthPtr--;
@@ -7134,6 +7143,7 @@
break;
//let extra semantic action decide when to push
case TokenNameRBRACKET :
+ this.rBracketPosition = this.scanner.startPosition;
this.endPosition = this.scanner.startPosition;
this.endStatementPosition = this.scanner.currentPosition - 1;
break;
@@ -8237,7 +8247,7 @@
ref.sourceEnd = this.intStack[this.intPtr--];
} else {
this.intPtr--;
- ref.sourceEnd = this.endPosition;
+ ref.sourceEnd = this.rBracketPosition;
}
} else {
int numberOfIdentifiers = this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr--];
@@ -8663,6 +8673,7 @@
this.rBraceStart = 0;
this.rBraceEnd = 0;
this.rBraceSuccessorStart = 0;
+ this.rBracketPosition = 0;
this.genericsIdentifiersLengthPtr = -1;
this.genericsLengthPtr = -1;
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 d5d5830..7fb80fa 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
@@ -47,6 +47,8 @@
* Bug 428366 - [1.8] [compiler] The method valueAt(ObservableList<Object>, int) is ambiguous for the type Bindings
* Bug 416190 - [1.8][null] detect incompatible overrides due to null type annotations
* Bug 392245 - [1.8][compiler][null] Define whether / how @NonNullByDefault applies to TYPE_USE locations
+ * Bug 390889 - [1.8][compiler] Evaluate options to support 1.7- projects against 1.8 JRE.
+ * Bug 430150 - [1.8][null] stricter checking against type variables
* Jesper S Moller <jesper@selskabet.org> - Contributions for
* bug 382701 - [1.8][compiler] Implement semantic analysis of Lambda expressions & Reference expression
* bug 382721 - [1.8][compiler] Effectively final variables needs special treatment
@@ -393,6 +395,8 @@
case IProblem.CannotImplementIncompatibleNullness:
case IProblem.ConflictingNullAnnotations:
case IProblem.ConflictingInheritedNullAnnotations:
+ case IProblem.NullNotCompatibleToFreeTypeVariable:
+ case IProblem.NullityMismatchAgainstFreeTypeVariable:
case IProblem.NullityMismatchingTypeAnnotation:
case IProblem.NullityMismatchingTypeAnnotationSuperHint:
case IProblem.NullityMismatchTypeArgument:
@@ -1574,7 +1578,7 @@
this.handle(
IProblem.IncompatibleTypesInConditionalOperator,
new String[] {new String(trueType.readableName()), new String(falseType.readableName())},
- new String[] {new String(trueType.sourceName()), new String(falseType.sourceName())},
+ new String[] {new String(trueType.shortReadableName()), new String(falseType.shortReadableName())},
expression.sourceStart,
expression.sourceEnd);
}
@@ -1808,11 +1812,15 @@
importRef.sourceEnd);
}
-public void duplicateInheritedMethods(SourceTypeBinding type, MethodBinding inheritedMethod1, MethodBinding inheritedMethod2) {
+public void duplicateInheritedMethods(SourceTypeBinding type, MethodBinding inheritedMethod1, MethodBinding inheritedMethod2, boolean isJava8) {
if (TypeBinding.notEquals(inheritedMethod1.declaringClass, inheritedMethod2.declaringClass)) {
- int problemID = (inheritedMethod1.isDefaultMethod() && inheritedMethod2.isDefaultMethod())
- ? IProblem.DuplicateInheritedDefaultMethods
- : IProblem.DuplicateInheritedMethods;
+ int problemID = IProblem.DuplicateInheritedMethods;
+ if (inheritedMethod1.isDefaultMethod() && inheritedMethod2.isDefaultMethod()) {
+ if (isJava8)
+ problemID = IProblem.DuplicateInheritedDefaultMethods;
+ else
+ return; // don't report this error at 1.7-
+ }
this.handle(
problemID,
new String[] {
@@ -2228,8 +2236,8 @@
if (severity == ProblemSeverities.Ignore) return;
this.handle(
IProblem.FinalBoundForTypeVariable,
- new String[] { new String(typeVariable.sourceName), new String(typeRef.resolvedType.readableName())},
- new String[] { new String(typeVariable.sourceName), new String(typeRef.resolvedType.shortReadableName())},
+ new String[] { new String(typeVariable.sourceName()), new String(typeRef.resolvedType.readableName())},
+ new String[] { new String(typeVariable.sourceName()), new String(typeRef.resolvedType.shortReadableName())},
severity,
typeRef.sourceStart,
typeRef.sourceEnd);
@@ -2962,16 +2970,16 @@
IProblem.DefaultMethodNotBelow18,
NoArgument,
NoArgument,
- md.bodyStart,
- md.bodyEnd);
+ md.sourceStart,
+ md.sourceEnd);
}
public void staticInterfaceMethodsNotBelow18(MethodDeclaration md) {
this.handle(
IProblem.StaticInterfaceMethodNotBelow18,
NoArgument,
NoArgument,
- md.bodyStart,
- md.bodyEnd);
+ md.sourceStart,
+ md.sourceEnd);
}
public void referenceExpressionsNotBelow18(ReferenceExpression rexp) {
this.handle(
@@ -3576,7 +3584,7 @@
new String(shownConstructor.declaringClass.readableName()),
typesAsString(invocationArguments, false),
new String(inferredTypeArgument.readableName()),
- new String(typeParameter.sourceName),
+ new String(typeParameter.sourceName()),
parameterBoundAsString(typeParameter, false) },
new String[] {
new String(shownConstructor.declaringClass.sourceName()),
@@ -3584,7 +3592,7 @@
new String(shownConstructor.declaringClass.shortReadableName()),
typesAsString(invocationArguments, true),
new String(inferredTypeArgument.shortReadableName()),
- new String(typeParameter.sourceName),
+ new String(typeParameter.sourceName()),
parameterBoundAsString(typeParameter, true) },
sourceStart,
sourceEnd);
@@ -4124,7 +4132,7 @@
new String(shownMethod.declaringClass.readableName()),
typesAsString(invocationArguments, false),
new String(inferredTypeArgument.readableName()),
- new String(typeParameter.sourceName),
+ new String(typeParameter.sourceName()),
parameterBoundAsString(typeParameter, false) },
new String[] {
new String(shownMethod.selector),
@@ -4132,7 +4140,7 @@
new String(shownMethod.declaringClass.shortReadableName()),
typesAsString(invocationArguments, true),
new String(inferredTypeArgument.shortReadableName()),
- new String(typeParameter.sourceName),
+ new String(typeParameter.sourceName()),
parameterBoundAsString(typeParameter, true) },
(int) (messageSend.nameSourcePosition >>> 32),
(int) messageSend.nameSourcePosition);
@@ -4953,7 +4961,7 @@
new String(shownConstructor.declaringClass.readableName()),
typesAsString(invocationArguments, false),
new String(inferredTypeArgument.readableName()),
- new String(typeParameter.sourceName),
+ new String(typeParameter.sourceName()),
parameterBoundAsString(typeParameter, false) },
new String[] {
new String(shownConstructor.declaringClass.sourceName()),
@@ -4961,7 +4969,7 @@
new String(shownConstructor.declaringClass.shortReadableName()),
typesAsString(invocationArguments, true),
new String(inferredTypeArgument.shortReadableName()),
- new String(typeParameter.sourceName),
+ new String(typeParameter.sourceName()),
parameterBoundAsString(typeParameter, true) },
severity,
sourceStart,
@@ -5185,7 +5193,7 @@
new String(shownMethod.declaringClass.readableName()),
typesAsString(invocationArguments, false),
new String(inferredTypeArgument.readableName()),
- new String(typeParameter.sourceName),
+ new String(typeParameter.sourceName()),
parameterBoundAsString(typeParameter, false) },
new String[] {
new String(shownMethod.selector),
@@ -5193,7 +5201,7 @@
new String(shownMethod.declaringClass.shortReadableName()),
typesAsString(invocationArguments, true),
new String(inferredTypeArgument.shortReadableName()),
- new String(typeParameter.sourceName),
+ new String(typeParameter.sourceName()),
parameterBoundAsString(typeParameter, true) },
severity,
(int) (messageSend.nameSourcePosition >>> 32),
@@ -7809,6 +7817,10 @@
expectedType = expectedType.erasure();
}
if (actualType != null && (actualType.tagBits & TagBits.HasMissingType) != 0) { // improve secondary error
+ if (location instanceof Annotation) {
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=376977
+ return; // Already reported, don't report a secondary error
+ }
this.handle(
IProblem.UndefinedType,
new String[] {new String(actualType.leafComponentType().readableName())},
@@ -7854,8 +7866,8 @@
if (location == null) { // binary case
this.handle(
IProblem.TypeArgumentMismatch,
- new String[] { new String(typeArgument.readableName()), new String(genericType.readableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, false) },
- new String[] { new String(typeArgument.shortReadableName()), new String(genericType.shortReadableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, true) },
+ new String[] { new String(typeArgument.readableName()), new String(genericType.readableName()), new String(typeParameter.sourceName()), parameterBoundAsString(typeParameter, false) },
+ new String[] { new String(typeArgument.shortReadableName()), new String(genericType.shortReadableName()), new String(typeParameter.sourceName()), parameterBoundAsString(typeParameter, true) },
ProblemSeverities.AbortCompilation | ProblemSeverities.Error | ProblemSeverities.Fatal,
0,
0);
@@ -7863,8 +7875,8 @@
}
this.handle(
IProblem.TypeArgumentMismatch,
- new String[] { new String(typeArgument.readableName()), new String(genericType.readableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, false) },
- new String[] { new String(typeArgument.shortReadableName()), new String(genericType.shortReadableName()), new String(typeParameter.sourceName), parameterBoundAsString(typeParameter, true) },
+ new String[] { new String(typeArgument.readableName()), new String(genericType.readableName()), new String(typeParameter.sourceName()), parameterBoundAsString(typeParameter, false) },
+ new String[] { new String(typeArgument.shortReadableName()), new String(genericType.shortReadableName()), new String(typeParameter.sourceName()), parameterBoundAsString(typeParameter, true) },
location.sourceStart,
location.sourceEnd);
}
@@ -9157,20 +9169,28 @@
nullityMismatchingTypeAnnotation(expression, providedType, requiredType, NullAnnotationMatching.NULL_ANNOTATIONS_UNCHECKED);
}
public void nullityMismatchIsNull(Expression expression, TypeBinding requiredType) {
+ int problemId = IProblem.RequiredNonNullButProvidedNull;
+ boolean below18 = this.options.sourceLevel < ClassFileConstants.JDK1_8;
+ if (!below18 && requiredType.isTypeVariable() && !requiredType.hasNullTypeAnnotations())
+ problemId = IProblem.NullNotCompatibleToFreeTypeVariable;
if (requiredType instanceof CaptureBinding) {
CaptureBinding capture = (CaptureBinding) requiredType;
if (capture.wildcard != null)
requiredType = capture.wildcard;
}
- int problemId = IProblem.RequiredNonNullButProvidedNull;
String[] arguments;
String[] argumentsShort;
- if (this.options.sourceLevel < ClassFileConstants.JDK1_8) {
+ if (below18) {
arguments = new String[] { annotatedTypeName(requiredType, this.options.nonNullAnnotationName) };
argumentsShort = new String[] { shortAnnotatedTypeName(requiredType, this.options.nonNullAnnotationName) };
} else {
- arguments = new String[] { new String(requiredType.nullAnnotatedReadableName(this.options, false)) };
- argumentsShort = new String[] { new String(requiredType.nullAnnotatedReadableName(this.options, true)) };
+ if (problemId == IProblem.NullNotCompatibleToFreeTypeVariable) {
+ arguments = new String[] { new String(requiredType.sourceName()) }; // don't show any bounds
+ argumentsShort = new String[] { new String(requiredType.sourceName()) };
+ } else {
+ arguments = new String[] { new String(requiredType.nullAnnotatedReadableName(this.options, false)) };
+ argumentsShort = new String[] { new String(requiredType.nullAnnotatedReadableName(this.options, true)) };
+ }
}
this.handle(problemId, arguments, argumentsShort, expression.sourceStart, expression.sourceEnd);
}
@@ -9456,10 +9476,6 @@
this.handle(problemId, args, shortArgs, start, end);
}
-public void nonNullDefaultDetailNotEvaluated(ASTNode location) {
- this.handle(IProblem.NonNullDefaultDetailIsNotEvaluated, NoArgument, NoArgument, ProblemSeverities.Warning, location.sourceStart, location.sourceEnd);
-}
-
public void contradictoryNullAnnotations(Annotation annotation) {
contradictoryNullAnnotations(annotation.sourceStart, annotation.sourceEnd);
}
@@ -9706,23 +9722,47 @@
String[] shortArguments;
int problemId = 0;
+ String superHint = null;
+ String superHintShort = null;
if (status.superTypeHint != null) {
problemId = (status.isUnchecked()
? IProblem.NullityUncheckedTypeAnnotationDetailSuperHint
: IProblem.NullityMismatchingTypeAnnotationSuperHint);
- arguments = new String[] { null, null, status.superTypeHintName(this.options, false) };
- shortArguments = new String[] { null, null, status.superTypeHintName(this.options, true) };
+ superHint = status.superTypeHintName(this.options, false);
+ superHintShort = status.superTypeHintName(this.options, true);
} else {
problemId = (status.isUnchecked()
? IProblem.NullityUncheckedTypeAnnotationDetail
- : IProblem.NullityMismatchingTypeAnnotation);
- arguments = new String[2];
- shortArguments = new String[2];
+ : (requiredType.isTypeVariable() && !requiredType.hasNullTypeAnnotations())
+ ? IProblem.NullityMismatchAgainstFreeTypeVariable
+ : IProblem.NullityMismatchingTypeAnnotation);
+ if (problemId == IProblem.NullityMismatchAgainstFreeTypeVariable) {
+ arguments = new String[] { null, null, new String(requiredType.sourceName()) }; // don't show bounds here
+ shortArguments = new String[] { null, null, new String(requiredType.sourceName()) };
+ } else {
+ arguments = new String[2];
+ shortArguments = new String[2];
+ }
}
- arguments[0] = String.valueOf(requiredType.nullAnnotatedReadableName(this.options, false));
- arguments[1] = String.valueOf(providedType.nullAnnotatedReadableName(this.options, false));
- shortArguments[0] = String.valueOf(requiredType.nullAnnotatedReadableName(this.options, true));
- shortArguments[1] = String.valueOf(providedType.nullAnnotatedReadableName(this.options, true));
+ String requiredName;
+ String requiredNameShort;
+ if (problemId == IProblem.NullityMismatchAgainstFreeTypeVariable) {
+ requiredName = new String(requiredType.sourceName()); // don't show bounds here
+ requiredNameShort = new String(requiredType.sourceName()); // don't show bounds here
+ } else {
+ requiredName = new String(requiredType.nullAnnotatedReadableName(this.options, false));
+ requiredNameShort = new String(requiredType.nullAnnotatedReadableName(this.options, true));
+ }
+ String providedName = String.valueOf(providedType.nullAnnotatedReadableName(this.options, false));
+ String providedNameShort = String.valueOf(providedType.nullAnnotatedReadableName(this.options, true));
+ // assemble arguments:
+ if (superHint != null) {
+ arguments = new String[] { requiredName, providedName, superHint };
+ shortArguments = new String[] { requiredNameShort, providedNameShort, superHintShort };
+ } else {
+ arguments = new String[] { requiredName, providedName };
+ shortArguments = new String[] { requiredNameShort, providedNameShort };
+ }
this.handle(problemId, arguments, shortArguments, expression.sourceStart, expression.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 8dc1e3e..dfaddb3 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
@@ -37,6 +37,7 @@
# Bug 418743 - [1.8][null] contradictory annotations on invocation of generic method not reported
# Bug 416190 - [1.8][null] detect incompatible overrides due to null type annotations
# Bug 392245 - [1.8][compiler][null] Define whether / how @NonNullByDefault applies to TYPE_USE locations
+# Bug 430150 - [1.8][null] stricter checking against type variables
# 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
@@ -820,7 +821,9 @@
965 = This nullness annotation conflicts with a ''@{0}'' annotation which is effective on the same type parameter
966 = Contradictory null annotations: method was inferred as ''{2} {3}({4})'', but only one of ''@{0}'' and ''@{1}'' can be effective at any location
967 = Null type safety: Unchecked cast from {0} to {1}
-968 = Arguments controling the details of the nullness default are not yet evaluated by the analysis.
+#968 temporary warning has been removed
+969 = Null type mismatch (type annotations): ''null'' is not compatible to the free type variable ''{0}''
+970 = Null type mismatch (type annotations): required ''{0}'' but this expression has type ''{1}'', where ''{0}'' is a free type variable
# Java 8
1001 = Syntax error, modifiers and annotations are not allowed for the lambda parameter {0} as its type is elided
@@ -837,22 +840,22 @@
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.
+1058 = Default methods are allowed only in interfaces.
1100 = Problem detected during type inference: {0}
1101 = (Recovered) Internal inconsistency detected during lambda shape analysis
### ELABORATIONS
## Access restrictions
-78592 = The type {1} is not accessible due to restriction on classpath entry {0}
-78593 = The type {1} is not accessible due to restriction on required project {0}
-78594 = The type {1} is not accessible due to restriction on required library {0}
-78596 = The field {1} from the type {2} is not accessible due to restriction on classpath entry {0}
-78597 = The field {1} from the type {2} is not accessible due to restriction on required project {0}
-78598 = The field {1} from the type {2} is not accessible due to restriction on required library {0}
-78600 = The constructor {1} is not accessible due to restriction on classpath entry {0}
-78601 = The constructor {1} is not accessible due to restriction on required project {0}
-78602 = The constructor {1} is not accessible due to restriction on required library {0}
-78604 = The method {1} from the type {2} is not accessible due to restriction on classpath entry {0}
-78606 = The method {1} from the type {2} is not accessible due to restriction on required library {0}
-78605 = The method {1} from the type {2} is not accessible due to restriction on required project {0}
+78592 = The type ''{1}'' is not API (restriction on classpath entry ''{0}'')
+78593 = The type ''{1}'' is not API (restriction on required project ''{0}'')
+78594 = The type ''{1}'' is not API (restriction on required library ''{0}'')
+78596 = The field ''{2}.{1}'' is not API (restriction on classpath entry ''{0}'')
+78597 = The field ''{2}.{1}'' is not API (restriction on required project ''{0}'')
+78598 = The field ''{2}.{1}'' is not API (restriction on required library ''{0}'')
+78600 = The constructor ''{1}'' is not API (restriction on classpath entry ''{0}'')
+78601 = The constructor ''{1}'' is not API (restriction on required project ''{0}'')
+78602 = The constructor ''{1}'' is not API (restriction on required library ''{0}'')
+78604 = The method ''{2}.{1}'' is not API (restriction on classpath entry ''{0}'')
+78606 = The method ''{2}.{1}'' is not API (restriction on required library ''{0}'')
+78605 = The method ''{2}.{1}'' is not API (restriction on required project ''{0}'')
\ No newline at end of file
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 913307b..604effa 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
@@ -533,6 +533,8 @@
methodName.internalSetIdentifier(new String(methodDeclaration.selector));
int start = methodDeclaration.sourceStart;
int end = retrieveIdentifierEndPosition(start, methodDeclaration.sourceEnd);
+ if (end < start)
+ end = start + methodDeclaration.selector.length;// naive recovery with method name
methodName.setSourceRange(start, end - start + 1);
methodDecl.setName(methodName);
org.eclipse.jdt.internal.compiler.ast.TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions;
@@ -2758,7 +2760,7 @@
}
if (statement instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
ASTNode result = convert((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) statement);
- if (result == null) {
+ if (result == null || !(result instanceof TypeDeclaration)) {
return createFakeEmptyStatement(statement);
}
// annotation and enum type declarations are not returned by the parser inside method bodies
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java
index 68dcb42..9e86e96 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTRecoveryPropagator.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2013 IBM Corporation and others.
+ * Copyright (c) 2006, 2014 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
@@ -89,9 +89,6 @@
private Vector stack = new Vector();
- /**
- * @noreference This method is not intended to be referenced by clients.
- */
ASTRecoveryPropagator(CategorizedProblem[] problems, RecoveryScannerData data) {
// visit Javadoc.tags() as well
this.problems = problems;
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CreationReference.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CreationReference.java
index 933265b..cef5dd0 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CreationReference.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/CreationReference.java
@@ -36,7 +36,7 @@
new ChildPropertyDescriptor(CreationReference.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
/**
- * The "typeArguments" structural property of this node type (element type: {@link Type})
+ * The "typeArguments" structural property of this node type (element type: {@link Type}).
*/
public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
internalTypeArgumentsFactory(CreationReference.class);
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionMethodReference.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionMethodReference.java
index 8a65abc..ee15680 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionMethodReference.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ExpressionMethodReference.java
@@ -41,7 +41,7 @@
internalTypeArgumentsFactory(ExpressionMethodReference.class);
/**
- * The "name" structural property of this node type (child type: {@link SimpleName}.
+ * The "name" structural property of this node type (child type: {@link SimpleName}).
*/
public static final ChildPropertyDescriptor NAME_PROPERTY =
new ChildPropertyDescriptor(ExpressionMethodReference.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java
index c2324da..3a0f5d5 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodBinding.java
@@ -205,8 +205,11 @@
final ReferenceBinding annotationType = internalAnnotation.getAnnotationType();
long metaTagBits = annotationType.getAnnotationTagBits();
- if (isConstructor && (metaTagBits & TagBits.AnnotationForConstructor) == 0)
- continue; // must be type use.
+ // Exclude all other targets including TYPE_USE, even though TYPE_USE is accepted.
+ if (isConstructor && (metaTagBits & TagBits.AnnotationForConstructor) == 0 &&
+ ((metaTagBits & TagBits.AnnotationTargetMASK) != 0)) {
+ continue;
+ }
final IAnnotationBinding annotationInstance = this.resolver.getAnnotationInstance(internalAnnotation);
if (annotationInstance == null) {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
index e49f522..3959e63 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/MethodDeclaration.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -291,7 +291,6 @@
* The parameter declarations
* (element type: {@link SingleVariableDeclaration}).
* Defaults to an empty list.
- * @since 3.10 // Added because of @since check due to raising visibility
*/
// AspectJ extension - made protected instead of private
protected ASTNode.NodeList parameters =
@@ -762,7 +761,7 @@
* A receiver qualifier is only legal in Java code if it appears on a constructor of an inner class.
* </p>
*
- * @returns the qualifying name or <code>null</code> if a qualifier was not specified
+ * @return the qualifying name or <code>null</code> if a qualifier was not specified
* @exception UnsupportedOperationException if this operation is used below JLS8
* @since 3.10
*/
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java
index 6760e45..99ca7a1 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SingleVariableDeclaration.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -517,7 +517,13 @@
/**
* Returns the type of the variable declared in this variable declaration,
- * exclusive of any extra array dimensions.
+ * exclusive of any extra array dimensions or the varargs dimension.
+ * <p>
+ * WARNING: For array-typed varargs, the {@link Type#resolveBinding() binding}
+ * of the returned <code>Type</code> is not useful, since it represents
+ * an unused type. It misses the last (innermost) dimension that carries the
+ * {@link #varargsAnnotations()}.
+ * </p>
*
* @return the type
*/
@@ -560,7 +566,7 @@
* Returns whether this declaration declares the last parameter of
* a variable arity method (added in JLS3 API).
* <p>
- * Note that the binding for the type <code>Foo</code>in the vararg method
+ * Note that the binding for the type <code>Foo</code> in the vararg method
* declaration <code>void fun(Foo... args)</code> is always for the type as
* written; i.e., the type binding for <code>Foo</code>. However, if you
* navigate from the method declaration to its method binding to the
@@ -568,6 +574,12 @@
* parameter is always an array type (i.e., <code>Foo[]</code>) reflecting
* the way vararg methods get compiled.
* </p>
+ * <p>
+ * WARNING: For array-typed varargs, the {@link Type#resolveBinding() binding}
+ * of the variable's {@link #getType() type} is not useful, since it represents
+ * an unused type. It misses the last (innermost) dimension that carries the
+ * {@link #varargsAnnotations()}.
+ * </p>
*
* @return <code>true</code> if this is a variable arity parameter declaration,
* and <code>false</code> otherwise
@@ -603,10 +615,17 @@
/**
* Returns the ordered list of annotations on the varargs token (added in JLS8 API).
+ * <p>
+ * WARNING: For array-typed varargs, the {@link Type#resolveBinding() binding}
+ * of the variable's {@link #getType() type} is not useful, since it represents
+ * an unused type. It misses the last (innermost) dimension that carries the
+ * returned {@code varargsAnnotations}.
+ * </p>
*
* @return the list of annotations on the varargs token (element type: {@link Annotation})
* @exception UnsupportedOperationException if this operation is used
* in a JLS2, JLS3 or JLS4 AST
+ * @see #isVarargs()
* @since 3.10
*/
public List varargsAnnotations() {
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodReference.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodReference.java
index 458df91..5dcd654 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodReference.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/SuperMethodReference.java
@@ -36,7 +36,7 @@
new ChildPropertyDescriptor(SuperMethodReference.class, "qualifier", Name.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$
/**
- * The "typeArguments" structural property of this node type (element type: {@link Type})
+ * The "typeArguments" structural property of this node type (element type: {@link Type}).
*/
public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
internalTypeArgumentsFactory(SuperMethodReference.class);
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeMethodReference.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeMethodReference.java
index c791485..c656ad3 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeMethodReference.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TypeMethodReference.java
@@ -35,13 +35,13 @@
new ChildPropertyDescriptor(TypeMethodReference.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
/**
- * The "typeArguments" structural property of this node type (element type: {@link Type})
+ * The "typeArguments" structural property of this node type (element type: {@link Type}).
*/
public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY =
internalTypeArgumentsFactory(TypeMethodReference.class);
/**
- * The "name" structural property of this node type (child type: {@link SimpleName}.
+ * The "name" structural property of this node type (child type: {@link SimpleName}).
*/
public static final ChildPropertyDescriptor NAME_PROPERTY =
new ChildPropertyDescriptor(TypeMethodReference.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java
index 8a3708a..922467c 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/rewrite/ImportRewrite.java
@@ -143,12 +143,12 @@
private boolean useContextToFilterImplicitImports;
/**
- * Creates a {@link ImportRewrite} from a {@link ICompilationUnit}. If <code>restoreExistingImports</code>
+ * Creates an {@link ImportRewrite} from an {@link ICompilationUnit}. If <code>restoreExistingImports</code>
* is <code>true</code>, all existing imports are kept, and new imports will be inserted at best matching locations. If
* <code>restoreExistingImports</code> is <code>false</code>, the existing imports will be removed and only the
* newly added imports will be created.
* <p>
- * Note that {@link #create(ICompilationUnit, boolean)} is more efficient than this method if an AST for
+ * Note that {@link #create(CompilationUnit, boolean)} is more efficient than this method if an AST for
* the compilation unit is already available.
* </p>
* @param cu the compilation unit to create the imports for
@@ -174,7 +174,7 @@
}
/**
- * Creates a {@link ImportRewrite} from a an AST ({@link CompilationUnit}). The AST has to be created from a
+ * Creates an {@link ImportRewrite} from an AST ({@link CompilationUnit}). The AST has to be created from an
* {@link ICompilationUnit}, that means {@link ASTParser#setSource(ICompilationUnit)} has been used when creating the
* AST. If <code>restoreExistingImports</code> is <code>true</code>, all existing imports are kept, and new imports
* will be inserted at best matching locations. If <code>restoreExistingImports</code> is <code>false</code>, the
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
index 66724a8..31bf9ef 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ICompilationUnit.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -33,6 +33,7 @@
*
* @noimplement This interface is not intended to be implemented by clients.
*/
+@SuppressWarnings("deprecation")
public interface ICompilationUnit extends ITypeRoot, IWorkingCopy, ISourceManipulation {
/**
* Constant indicating that a reconcile operation should not return an AST.
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
index 7f12435..df0b898 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -17,11 +17,15 @@
/**
* Represents either a source type in a compilation unit (either a top-level
- * type, a member type, a local type or an anonymous type)
+ * type, a member type, a local type, an anonymous type or a lambda expression)
* or a binary type in a class file. Enumeration classes and annotation
* types are subkinds of classes and interfaces, respectively.
* <p>
- * Note that the element name of an anonymous source type is always empty.
+ * Note that the element name of an anonymous source type and lambda expressions
+ * is always empty. Types representing lambda expressions are pseudo-elements
+ * and not included in the children of their parent. Lambda expressions are created
+ * as the result of a <code>ICodeAssist.codeSelect(...)</code>. For more information
+ * on such pseudo-elements, see <code>ILocalVariable</code>.
* </p><p>
* If a binary type cannot be parsed, its structure remains unknown.
* Use <code>IJavaElement.isStructureKnown</code> to determine whether this
@@ -486,6 +490,9 @@
/**
* Returns the simple name of this type, unqualified by package or enclosing type.
* This is a handle-only method.
+ *
+ * Note that the element name of an anonymous source type and lambda expressions
+ * is always empty.
*
* @return the simple name of this type
*/
@@ -1205,4 +1212,12 @@
* @since 3.0
*/
String[][] resolveType(String typeName, WorkingCopyOwner owner) throws JavaModelException;
+
+ /**
+ * Returns whether this type represents a lambda expression.
+ *
+ * @return true if this type represents a lambda expression, false otherwise
+ * @since 3.10
+ */
+ public boolean isLambda();
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
index 3e4794e..3a94cad 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -271,8 +271,9 @@
*/
public static final String COMPILER_CODEGEN_UNUSED_LOCAL = PLUGIN_ID + ".compiler.codegen.unusedLocal"; //$NON-NLS-1$
/**
- * Compiler option ID: Generating Method Parameters Attribute.
- * <p>When generated, this attribute will enable parameter names to be accessed from reflection libraries, annotation processing,
+ * Compiler option ID: Generating Method Parameters Attribute.
+ * <p>When generated, this attribute will enable information about the formal parameters of a method
+ * (such as their names) to be accessed from reflection libraries, annotation processing,
* code weaving, and in the debugger, from platform target level 1.8 and later.</p>
* <dl>
* <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.compiler.codegen.methodParameters"</code></dd>
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
index 7b3e1c4..ddfe577 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/SourceElementParser.java
@@ -751,7 +751,7 @@
ref.sourceEnd = this.intStack[this.intPtr--];
} else {
this.intPtr--; // no need to use this position as it is an array
- ref.sourceEnd = this.endPosition;
+ ref.sourceEnd = this.rBracketPosition;
}
if (this.reportReferenceInfo){
this.requestor.acceptTypeReference(ref.getParameterizedTypeName(), ref.sourceStart, ref.sourceEnd);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryLambdaExpression.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryLambdaExpression.java
new file mode 100644
index 0000000..fad0f59
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryLambdaExpression.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.IJavaElement;
+
+
+public class BinaryLambdaExpression extends LambdaExpression {
+
+ BinaryLambdaExpression(JavaElement parent, org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambdaExpression) {
+ super(parent, lambdaExpression);
+ }
+
+ BinaryLambdaExpression(JavaElement parent, String interphase, int sourceStart, int sourceEnd, int arrowPosition) {
+ super(parent, interphase, sourceStart, sourceEnd, arrowPosition);
+ }
+
+ BinaryLambdaExpression(JavaElement parent, String interphase, int sourceStart, int sourceEnd, int arrowPosition, LambdaMethod lambdaMethod) {
+ super(parent, interphase, sourceStart, sourceEnd, arrowPosition, lambdaMethod);
+ }
+
+ /*
+ * @see JavaElement#getPrimaryElement(boolean)
+ */
+ public IJavaElement getPrimaryElement(boolean checkOwner) {
+ return this;
+ }
+
+ /*
+ * @see IMember#isBinary()
+ */
+ public boolean isBinary() {
+ return true;
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryLambdaMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryLambdaMethod.java
new file mode 100644
index 0000000..ee19f6c
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryLambdaMethod.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.IJavaElement;
+
+public class BinaryLambdaMethod extends LambdaMethod {
+
+ BinaryLambdaMethod(JavaElement parent, String name, String key, int sourceStart, String [] parameterTypes, String [] parameterNames, String returnType, SourceMethodElementInfo elementInfo) {
+ super(parent, name, key, sourceStart, parameterTypes, parameterNames, returnType, elementInfo);
+ }
+
+ /*
+ * @see JavaElement#getPrimaryElement(boolean)
+ */
+ public IJavaElement getPrimaryElement(boolean checkOwner) {
+ return this;
+ }
+
+ /*
+ * @see IMember#isBinary()
+ */
+ public boolean isBinary() {
+ return true;
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java
index 7e7cccb..53c3883 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryMethod.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Terry Parker <tparker@google.com> - Bug 418092
*******************************************************************************/
package org.eclipse.jdt.internal.core;
@@ -28,6 +29,7 @@
import org.eclipse.jdt.internal.compiler.env.IBinaryType;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
+import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jdt.internal.core.JavaModelManager.PerProjectInfo;
import org.eclipse.jdt.internal.core.util.Util;
@@ -353,7 +355,13 @@
}
}
if (methodDoc != null) {
- final int indexOfOpenParen = methodDoc.indexOf('(');
+ int indexOfOpenParen = methodDoc.indexOf('(');
+ // Annotations may have parameters, so make sure we are parsing the actual method parameters.
+ if (info.getAnnotations() != null) {
+ while (indexOfOpenParen != -1 && !isOpenParenForMethod(methodDoc, getElementName(), indexOfOpenParen)) {
+ indexOfOpenParen = methodDoc.indexOf('(', indexOfOpenParen + 1);
+ }
+ }
if (indexOfOpenParen != -1) {
final int indexOfClosingParen = methodDoc.indexOf(')', indexOfOpenParen);
if (indexOfClosingParen != -1) {
@@ -391,6 +399,33 @@
// If still no parameter names, produce fake ones, but don't cache them (https://bugs.eclipse.org/bugs/show_bug.cgi?id=329671)
return getRawParameterNames(paramCount);
}
+private boolean isOpenParenForMethod(String javaDoc, String methodName, int index) {
+ /*
+ * Annotations can have parameters associated with them, so we need to validate that this parameter list is
+ * actually for the method. Determine this by scanning backwards from where the paren was seen, skipping over
+ * HTML tags to find the identifier that precedes the paren, and then matching that identifier against the
+ * method's name.
+ */
+ boolean scanningTag = false;
+ int endIndex = 0;
+ while (--index > methodName.length()) {
+ char previousChar = javaDoc.charAt(index);
+ if (endIndex > 0) {
+ if (!ScannerHelper.isJavaIdentifierPart(previousChar)
+ || !ScannerHelper.isJavaIdentifierStart(previousChar))
+ return methodName.equals(javaDoc.substring(index + 1, endIndex));
+ } else if (!scanningTag) {
+ if (previousChar == '>')
+ scanningTag = true;
+ else if (ScannerHelper.isJavaIdentifierPart(previousChar)
+ || ScannerHelper.isJavaIdentifierStart(previousChar))
+ endIndex = index + 1;
+ } else if (previousChar == '<')
+ // We are only matching angle brackets here, without any other validation of the tags.
+ scanningTag = false;
+ }
+ return false;
+}
private char[][] splitParameters(char[] parametersSource, int paramCount) {
// we have generic types as one of the parameter types
char[][] params = new char[paramCount][];
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
index e26c0b8..a2ced80 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -391,6 +391,7 @@
params.toArray(parameters);
JavaElement method = (JavaElement)getMethod(selector, parameters);
switch (token.charAt(0)) {
+ case JEM_LAMBDA_EXPRESSION:
case JEM_TYPE:
case JEM_TYPE_PARAMETER:
case JEM_LOCALVARIABLE:
@@ -1035,11 +1036,15 @@
pathBuffer.append(pack.getElementName().replace('.', '/')).append('/').append(typeQualifiedName).append(JavadocConstants.HTML_EXTENSION);
if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
- final String contents = getURLContents(String.valueOf(pathBuffer));
+ final String contents = getURLContents(baseLocation, String.valueOf(pathBuffer));
JavadocContents javadocContents = new JavadocContents(this, contents);
synchronized (projectInfo.javadocCache) {
projectInfo.javadocCache.put(this, javadocContents);
}
return javadocContents;
}
+@Override
+public boolean isLambda() {
+ return false;
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
index fad6d39..d656423 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnitStructureRequestor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -728,7 +728,7 @@
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=342393
// For anonymous source types, the occurrence count should be in the context
// of the enclosing type.
- if (handle instanceof SourceType && handle.getElementName().length() == 0) {
+ if (handle instanceof SourceType && ((SourceType) handle).isAnonymous()) {
Object key = handle.getParent().getAncestor(IJavaElement.TYPE);
occurenceCount = this.localOccurrenceCounts.get(key);
if (occurenceCount == -1)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java
index fd7ce3f..0d495e6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessingState.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -179,30 +179,36 @@
return deltaProcessor;
}
- public synchronized ClasspathChange addClasspathChange(IProject project, IClasspathEntry[] oldRawClasspath, IPath oldOutputLocation, IClasspathEntry[] oldResolvedClasspath) {
- ClasspathChange change = (ClasspathChange) this.classpathChanges.get(project);
- if (change == null) {
- change = new ClasspathChange((JavaProject) JavaModelManager.getJavaModelManager().getJavaModel().getJavaProject(project), oldRawClasspath, oldOutputLocation, oldResolvedClasspath);
- this.classpathChanges.put(project, change);
- } else {
- if (change.oldRawClasspath == null)
- change.oldRawClasspath = oldRawClasspath;
- if (change.oldOutputLocation == null)
- change.oldOutputLocation = oldOutputLocation;
- if (change.oldResolvedClasspath == null)
- change.oldResolvedClasspath = oldResolvedClasspath;
+ public ClasspathChange addClasspathChange(IProject project, IClasspathEntry[] oldRawClasspath, IPath oldOutputLocation, IClasspathEntry[] oldResolvedClasspath) {
+ synchronized (this.classpathChanges) {
+ ClasspathChange change = (ClasspathChange) this.classpathChanges.get(project);
+ if (change == null) {
+ change = new ClasspathChange((JavaProject) JavaModelManager.getJavaModelManager().getJavaModel().getJavaProject(project), oldRawClasspath, oldOutputLocation, oldResolvedClasspath);
+ this.classpathChanges.put(project, change);
+ } else {
+ if (change.oldRawClasspath == null)
+ change.oldRawClasspath = oldRawClasspath;
+ if (change.oldOutputLocation == null)
+ change.oldOutputLocation = oldOutputLocation;
+ if (change.oldResolvedClasspath == null)
+ change.oldResolvedClasspath = oldResolvedClasspath;
+ }
+ return change;
}
- return change;
}
- public synchronized ClasspathChange getClasspathChange(IProject project) {
- return (ClasspathChange) this.classpathChanges.get(project);
+ public ClasspathChange getClasspathChange(IProject project) {
+ synchronized (this.classpathChanges) {
+ return (ClasspathChange) this.classpathChanges.get(project);
+ }
}
- public synchronized HashMap removeAllClasspathChanges() {
- HashMap result = this.classpathChanges;
- this.classpathChanges = new HashMap(result.size());
- return result;
+ public HashMap removeAllClasspathChanges() {
+ synchronized (this.classpathChanges) {
+ HashMap result = this.classpathChanges;
+ this.classpathChanges = new HashMap(result.size());
+ return result;
+ }
}
public synchronized ClasspathValidation addClasspathValidation(JavaProject project) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
index a720993..71f98ab 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Terry Parker <tparker@google.com> - DeltaProcessor exhibits O(N^2) behavior, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=354332
* Terry Parker <tparker@google.com> - DeltaProcessor misses state changes in archive files, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=357425
+ * Terry Parker <tparker@google.com> - [performance] Low hit rates in JavaModel caches - https://bugs.eclipse.org/421165
*******************************************************************************/
package org.eclipse.jdt.internal.core;
@@ -16,6 +17,7 @@
import java.net.URL;
import java.util.*;
+import org.eclipse.core.resources.IBuildConfiguration;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
@@ -65,6 +67,9 @@
@SuppressWarnings({ "rawtypes", "unchecked" })
public class DeltaProcessor {
+ /*
+ * An object to hold information about a project's output folders (where .class files are generated).
+ */
static class OutputsInfo {
int outputCount;
IPath[] paths;
@@ -102,14 +107,20 @@
}
}
+ /*
+ * An object to hold information about IPackageFragmentRoots (which correspond to
+ * individual classpath entry items, e.g., a java/javatests source root or library
+ * archive jar.)
+ */
public static class RootInfo {
- char[][] inclusionPatterns;
- char[][] exclusionPatterns;
- public JavaProject project;
- IPath rootPath;
- int entryKind;
+ final char[][] inclusionPatterns;
+ final char[][] exclusionPatterns;
+ final public JavaProject project;
+ final IPath rootPath;
+ final int entryKind;
IPackageFragmentRoot root;
IPackageFragmentRoot cache;
+
RootInfo(JavaProject project, IPath rootPath, char[][] inclusionPatterns, char[][] exclusionPatterns, int entryKind) {
this.project = project;
this.rootPath = rootPath;
@@ -967,6 +978,9 @@
String status = (String)externalArchivesStatus.get(entryPath);
if (status == null){
+ // Clear the external file state for this path, since this method is responsible for updating it.
+ this.manager.clearExternalFileState(entryPath);
+
// compute shared status
Object targetLibrary = JavaModel.getTarget(entryPath, true);
@@ -1060,8 +1074,6 @@
javaProject.resetResolvedClasspath();
}
}
- // ensure the external file cache is reset so that if a .jar file is deleted but no longer on the classpath, it won't appear as changed next time it is added
- JavaModel.flushExternalFileCache();
if (hasDelta){
// flush jar type cache
@@ -1131,7 +1143,7 @@
if (elementType == IJavaElement.JAVA_PROJECT) {
// project add is handled by JavaProject.configure() because
- // when a project is created, it does not yet have a java nature
+ // when a project is created, it does not yet have a Java nature
IProject project;
if (delta != null && JavaProject.hasJavaNature(project = (IProject)delta.getResource())) {
addToParentInfo(element);
@@ -2156,7 +2168,39 @@
}
if (isAffected) {
- JavaModel.flushExternalFileCache();
+ Object source = event.getSource();
+ projects = null;
+ if (source instanceof IWorkspace) {
+ projects = ((IWorkspace) source).getRoot().getProjects();
+ } else if (source instanceof IProject) {
+ projects = new IProject[] {(IProject) source};
+ } else {
+ Util.log(new Exception(),
+ "Expected to see a workspace or project on the PRE_BUILD resource change but was: " + source.toString()); //$NON-NLS-1$
+ }
+ if (projects != null) {
+ // If we are about to do a build and a Java project's first builder is not the Java builder,
+ // then it is possible that one of the earlier builders will build a jar file that is on that
+ // project's classpath. If we see that, then to be safe we must flush the caching of the
+ // JavaModelManager's external file state.
+ // A possible further optimization for this situation where earlier builders can affect the
+ // Java builder would be to add a new classpath element attribute that identifies whether
+ // or not a library jar is "stable" and needs to be flushed.
+ for (int i = 0; i < projects.length; i++) {
+ try {
+ IProject project = projects[i];
+ if (project.isOpen() && project.hasNature(JavaCore.NATURE_ID)) {
+ IBuildConfiguration[] configs = project.getBuildConfigs();
+ if (configs.length > 1 && !JavaCore.BUILDER_ID.equals(configs[0].getName())) {
+ this.manager.resetExternalFilesCache();
+ break;
+ }
+ }
+ } catch (CoreException exception) {
+ Util.log(exception, "Exception while checking builder configuration ordering"); //$NON-NLS-1$
+ }
+ }
+ }
JavaBuilder.buildStarting();
}
@@ -2477,7 +2521,7 @@
}
/*
- * Update the current delta (i.e. add/remove/change the given element) and update the correponding index.
+ * Update the current delta (i.e. add/remove/change the given element) and update the corresponding index.
* Returns whether the children of the given delta must be processed.
* @throws a JavaModelException if the delta doesn't correspond to a java element of the given type.
*/
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java
index 5478eb5..07b3461 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Stephan Herrmann <stephan@cs.tu-berlin.de> - inconsistent initialization of classpath container backed by external class folder, see https://bugs.eclipse.org/320618
* Thirumala Reddy Mutchukota <thirumala@google.com> - Contribution to bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=411423
+ * Terry Parker <tparker@google.com> - [performance] Low hit rates in JavaModel caches - https://bugs.eclipse.org/421165
*******************************************************************************/
package org.eclipse.jdt.internal.core;
@@ -69,9 +70,9 @@
return MANAGER;
}
- /*
- * Returns a set of external path to external folders referred to on the given classpath.
- * Returns null if none.
+ /**
+ * Returns a set of external paths to external folders referred to on the given classpath.
+ * Returns <code>null</code> if there are none.
*/
public static HashSet getExternalFolders(IClasspathEntry[] classpath) {
if (classpath == null)
@@ -97,7 +98,9 @@
return folders;
}
-
+ /**
+ * Returns <code>true</code> if the provided path is a folder external to the project.
+ */
public static boolean isExternalFolderPath(IPath externalPath) {
if (externalPath == null)
return false;
@@ -105,14 +108,17 @@
if (firstSegment != null && ResourcesPlugin.getWorkspace().getRoot().getProject(firstSegment).exists())
return false;
JavaModelManager manager = JavaModelManager.getJavaModelManager();
- if (manager.isExternalFile(externalPath))
+ if (manager.isExternalFile(externalPath) || manager.isAssumedExternalFile(externalPath))
return false;
File externalFolder = externalPath.toFile();
- if (externalFolder.isFile()
- || (externalPath.getFileExtension() != null/*likely a .jar, .zip, .rar or other file*/ && !externalFolder.exists())) {
+ if (externalFolder.isFile()) {
manager.addExternalFile(externalPath);
return false;
}
+ if (externalPath.getFileExtension() != null/*likely a .jar, .zip, .rar or other file*/ && !externalFolder.exists()) {
+ manager.addAssumedExternalFile(externalPath);
+ return false;
+ }
return true;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceModifyListener.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceModifyListener.java
index 5fb1012..ffbc0d3 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceModifyListener.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceModifyListener.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -13,7 +13,7 @@
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.core.runtime.preferences.PreferenceModifyListener;
-import org.eclipse.jdt.core.*;
+import org.eclipse.jdt.core.JavaCore;
import org.osgi.service.prefs.BackingStoreException;
import org.osgi.service.prefs.Preferences;
@@ -26,8 +26,20 @@
* @see org.eclipse.core.runtime.preferences.PreferenceModifyListener#preApply(org.eclipse.core.runtime.preferences.IEclipsePreferences)
*/
public IEclipsePreferences preApply(IEclipsePreferences node) {
- Preferences instance = node.node(InstanceScope.SCOPE);
- cleanJavaCore(instance.node(JavaCore.PLUGIN_ID));
+ // the node does not need to be the root of the hierarchy
+ Preferences root = node.node("/"); //$NON-NLS-1$
+ try {
+ // we must not create empty preference nodes, so first check if the node exists
+ if (root.nodeExists(InstanceScope.SCOPE)) {
+ Preferences instance = root.node(InstanceScope.SCOPE);
+ // we must not create empty preference nodes, so first check if the node exists
+ if (instance.nodeExists(JavaCore.PLUGIN_ID)) {
+ cleanJavaCore(instance.node(JavaCore.PLUGIN_ID));
+ }
+ }
+ } catch (BackingStoreException e) {
+ // do nothing
+ }
return super.preApply(node);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
index 0c3e619..36ec69e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java
@@ -26,6 +26,8 @@
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.*;
@@ -73,6 +75,22 @@
public static final char JEM_LAMBDA_METHOD = '&';
public static final char JEM_STRING = '"';
+ /**
+ * Before ')', '&' and '"' became the newest additions as delimiters, the former two
+ * were allowed as part of element attributes and possibly stored. Trying to recreate
+ * elements from such memento would cause undesirable results. Consider the following
+ * valid project name: (abc)
+ * If we were to use ')' alone as the delimiter and decode the above name, the memento
+ * would be wrongly identified to contain a lambda expression.
+ *
+ * In order to differentiate delimiters from characters that are part of element attributes,
+ * the following escape character is being introduced and all the new delimiters must
+ * be escaped with this. So, a lambda expression would be written as: "=)..."
+ *
+ * @see JavaElement#appendEscapedDelimiter(StringBuffer, char)
+ */
+ public static final char JEM_DELIMITER_ESCAPE = JEM_JAVAPROJECT;
+
/**
* This element's parent, or <code>null</code> if this
@@ -82,6 +100,9 @@
protected static final JavaElement[] NO_ELEMENTS = new JavaElement[0];
protected static final Object NO_INFO = new Object();
+
+ private static Set<String> invalidURLs = null;
+ private static Set<String> validURLs = null;
/**
* Constructs a handle for a java element with
@@ -133,6 +154,16 @@
return getElementName().equals(other.getElementName()) &&
this.parent.equals(other.parent);
}
+ /**
+ * @see #JEM_DELIMITER_ESCAPE
+ */
+ protected void appendEscapedDelimiter(StringBuffer buffer, char delimiter) {
+ buffer.append(JEM_DELIMITER_ESCAPE);
+ buffer.append(delimiter);
+ }
+ /*
+ * Do not add new delimiters here
+ */
protected void escapeMementoName(StringBuffer buffer, String mementoName) {
for (int i = 0, length = mementoName.length(); i < length; i++) {
char character = mementoName.charAt(i);
@@ -153,9 +184,6 @@
case JEM_LOCALVARIABLE:
case JEM_TYPE_PARAMETER:
case JEM_ANNOTATION:
- case JEM_LAMBDA_EXPRESSION:
- case JEM_LAMBDA_METHOD:
- case JEM_STRING:
buffer.append(JEM_ESCAPE);
}
buffer.append(character);
@@ -744,10 +772,45 @@
}
/*
+ * This method caches a list of good and bad Javadoc locations in the current eclipse session.
+ */
+ protected void validateAndCache(URL baseLoc, FileNotFoundException e) throws JavaModelException {
+ String url = baseLoc.toString();
+ if (validURLs != null && validURLs.contains(url)) return;
+
+ if (invalidURLs != null && invalidURLs.contains(url))
+ throw new JavaModelException(e, IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC);
+
+ InputStream input = null;
+ try {
+ URLConnection connection = baseLoc.openConnection();
+ input = connection.getInputStream();
+ if (validURLs == null) {
+ validURLs = new HashSet<String>(1);
+ }
+ validURLs.add(url);
+ } catch (Exception e1) {
+ if (invalidURLs == null) {
+ invalidURLs = new HashSet<String>(1);
+ }
+ invalidURLs.add(url);
+ throw new JavaModelException(e, IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC);
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (Exception e1) {
+ // Ignore
+ }
+ }
+ }
+ }
+
+ /*
* We don't use getContentEncoding() on the URL connection, because it might leave open streams behind.
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=117890
*/
- protected String getURLContents(String docUrlValue) throws JavaModelException {
+ protected String getURLContents(URL baseLoc, String docUrlValue) throws JavaModelException {
InputStream stream = null;
JarURLConnection connection2 = null;
try {
@@ -831,8 +894,8 @@
} catch (MalformedURLException e) {
throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.CANNOT_RETRIEVE_ATTACHED_JAVADOC, this));
} catch (FileNotFoundException e) {
- // Ignore, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=120559 &
- // https://bugs.eclipse.org/bugs/show_bug.cgi?id=403036
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=403154
+ validateAndCache(baseLoc, e);
} catch (SocketException e) {
// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=247845 &
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=400060
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
index d9921f5..8e8a746 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -7,12 +7,12 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Terry Parker <tparker@google.com> - [performance] Low hit rates in JavaModel caches - https://bugs.eclipse.org/421165
*******************************************************************************/
package org.eclipse.jdt.internal.core;
import java.io.File;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.Map;
import org.eclipse.core.resources.IFile;
@@ -41,20 +41,6 @@
@SuppressWarnings({"rawtypes", "unchecked"})
public class JavaModel extends Openable implements IJavaModel {
- /**
- * A set of java.io.Files used as a cache of external jars that
- * are known to be existing.
- * Note this cache is kept for the whole session.
- */
- public static HashSet existingExternalFiles = new HashSet();
-
- /**
- * A set of external files ({@link #existingExternalFiles}) which have
- * been confirmed as file (i.e. which returns true to {@link java.io.File#isFile()}.
- * Note this cache is kept for the whole session.
- */
- public static HashSet existingExternalConfirmedFiles = new HashSet();
-
/**
* Constructs a new Java Model on the given workspace.
* Note that only one instance of JavaModel handle should ever be created.
@@ -148,13 +134,6 @@
public int getElementType() {
return JAVA_MODEL;
}
-/**
- * Flushes the cache of external files known to be existing.
- */
-public static void flushExternalFileCache() {
- existingExternalFiles = new HashSet();
- existingExternalConfirmedFiles = new HashSet();
-}
/*
* @see JavaElement
@@ -309,9 +288,16 @@
}
/**
- * Helper method - returns the targeted item (IResource if internal or java.io.File if external),
- * or null if unbound
- * Internal items must be referred to using container relative paths.
+ * Helper method - for the provided {@link IPath}, returns:
+ * <ul>
+ * <li>If the path corresponds to an internal file or folder, the {@link IResource} for that resource
+ * <li>If the path corresponds to an external folder linked through {@link ExternalFoldersManager},
+ * the {@link IFolder} for that folder
+ * <li>If the path corresponds to an external library archive, the {@link File} for that archive
+ * <li>Can return <code>null</code> if <code>checkResourceExistence</code> is <code>true</code>
+ * and the entity referred to by the path does not exist on the file system
+ * </ul>
+ * Internal items must be referred to using container-relative paths.
*/
public static Object getTarget(IPath path, boolean checkResourceExistence) {
Object target = getWorkspaceTarget(path); // Implicitly checks resource existence
@@ -319,6 +305,11 @@
return target;
return getExternalTarget(path, checkResourceExistence);
}
+
+/**
+ * Helper method - returns the {@link IResource} corresponding to the provided {@link IPath},
+ * or <code>null</code> if no such resource exists.
+ */
public static IResource getWorkspaceTarget(IPath path) {
if (path == null || path.getDevice() != null)
return null;
@@ -327,6 +318,13 @@
return null;
return workspace.getRoot().findMember(path);
}
+
+/**
+ * Helper method - returns either the linked {@link IFolder} or the {@link File} corresponding
+ * to the provided {@link IPath}. If <code>checkResourceExistence</code> is <code>false</code>,
+ * then the IFolder or File object is always returned, otherwise <code>null</code> is returned
+ * if it does not exist on the file system.
+ */
public static Object getExternalTarget(IPath path, boolean checkResourceExistence) {
if (path == null)
return null;
@@ -345,50 +343,48 @@
File externalFile = new File(path.toOSString());
if (!checkResourceExistence) {
return externalFile;
- } else if (existingExternalFilesContains(externalFile)) {
+ } else if (isExternalFile(path)) {
return externalFile;
- } else {
- if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
- System.out.println("(" + Thread.currentThread() + ") [JavaModel.getTarget(...)] Checking existence of " + path.toString()); //$NON-NLS-1$ //$NON-NLS-2$
- }
- if (externalFile.isFile()) { // isFile() checks for existence (it returns false if a directory)
- // cache external file
- existingExternalFilesAdd(externalFile);
- return externalFile;
- }
}
return null;
}
-private synchronized static void existingExternalFilesAdd(File externalFile) {
- existingExternalFiles.add(externalFile);
-}
-private synchronized static boolean existingExternalFilesContains(File externalFile) {
- return existingExternalFiles.contains(externalFile);
-}
/**
- * Helper method - returns whether an object is afile (i.e. which returns true to {@link java.io.File#isFile()}.
+ * Helper method - returns whether an object is a file (i.e., it returns <code>true</code>
+ * to {@link File#isFile()}.
*/
public static boolean isFile(Object target) {
- return getFile(target) != null;
+ if (target instanceof File) {
+ IPath path = Path.fromOSString(((File) target).getPath());
+ return isExternalFile(path);
+ }
+ return false;
}
/**
- * Helper method - returns the file item (i.e. which returns true to {@link java.io.File#isFile()},
- * or null if unbound
+ * Returns whether the provided path is an external file, checking and updating the
+ * JavaModelManager's external file cache.
*/
-public static synchronized File getFile(Object target) {
- if (existingExternalConfirmedFiles.contains(target))
- return (File) target;
- if (target instanceof File) {
- File f = (File) target;
- if (f.isFile()) {
- existingExternalConfirmedFiles.add(f);
- return f;
- }
+static private boolean isExternalFile(IPath path) {
+ if (JavaModelManager.getJavaModelManager().isExternalFile(path)) {
+ return true;
}
+ if (JavaModelManager.ZIP_ACCESS_VERBOSE) {
+ System.out.println("(" + Thread.currentThread() + ") [JavaModel.isExternalFile(...)] Checking existence of " + path.toString()); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ boolean isFile = path.toFile().isFile();
+ if (isFile) {
+ JavaModelManager.getJavaModelManager().addExternalFile(path);
+ }
+ return isFile;
+}
- return null;
+/**
+ * Helper method - returns the {@link File} item if <code>target</code> is a file (i.e., the target
+ * returns <code>true</code> to {@link File#isFile()}. Otherwise returns <code>null</code>.
+ */
+public static File getFile(Object target) {
+ return isFile(target) ? (File) target : null;
}
protected IStatus validateExistence(IResource underlyingResource) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
index d6de845..30bc98a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -13,6 +13,7 @@
* Stephan Herrmann - Contribution for Bug 346010 - [model] strange initialization dependency in OptionTests
* Terry Parker <tparker@google.com> - DeltaProcessor misses state changes in archive files, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=357425
* Thirumala Reddy Mutchukota <thirumala@google.com> - Contribution to bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=411423
+ * Terry Parker <tparker@google.com> - [performance] Low hit rates in JavaModel caches - https://bugs.eclipse.org/421165
*******************************************************************************/
package org.eclipse.jdt.internal.core;
@@ -91,6 +92,7 @@
private static final String NON_CHAINING_JARS_CACHE = "nonChainingJarsCache"; //$NON-NLS-1$
private static final String INVALID_ARCHIVES_CACHE = "invalidArchivesCache"; //$NON-NLS-1$
private static final String EXTERNAL_FILES_CACHE = "externalFilesCache"; //$NON-NLS-1$
+ private static final String ASSUMED_EXTERNAL_FILES_CACHE = "assumedExternalFilesCache"; //$NON-NLS-1$
/**
* Define a zip cache object.
@@ -1439,20 +1441,27 @@
private UserLibraryManager userLibraryManager;
/*
- * List of IPath of jars that are known to not contain a chaining (through MANIFEST.MF) to another library
+ * A set of IPaths for jars that are known to not contain a chaining (through MANIFEST.MF) to another library
*/
private Set nonChainingJars;
/*
- * List of IPath of jars that are known to be invalid - such as not being a valid/known format
+ * A set of IPaths for jars that are known to be invalid - such as not being a valid/known format
*/
private Set invalidArchives;
/*
- * List of IPath of files that are known to be external to the workspace
+ * A set of IPaths for files that are known to be external to the workspace.
+ * Need not be referenced by the classpath.
*/
private Set externalFiles;
+ /*
+ * A set of IPaths for files that do not exist on the file system but are assumed to be
+ * external archives (rather than external folders).
+ */
+ private Set assumedExternalFiles;
+
/**
* Update the classpath variable cache
*/
@@ -1588,6 +1597,7 @@
this.nonChainingJars = loadClasspathListCache(NON_CHAINING_JARS_CACHE);
this.invalidArchives = loadClasspathListCache(INVALID_ARCHIVES_CACHE);
this.externalFiles = loadClasspathListCache(EXTERNAL_FILES_CACHE);
+ this.assumedExternalFiles = loadClasspathListCache(ASSUMED_EXTERNAL_FILES_CACHE);
String includeContainerReferencedLib = System.getProperty(RESOLVE_REFERENCED_LIBRARIES_FOR_CONTAINERS);
this.resolveReferencedLibrariesForContainers = TRUE.equalsIgnoreCase(includeContainerReferencedLib);
}
@@ -1616,6 +1626,10 @@
}
}
+ /**
+ * Adds a path to the external files cache. It is the responsibility of callers to
+ * determine the file's existence, as determined by {@link File#isFile()}.
+ */
public void addExternalFile(IPath path) {
// unlikely to be null
if (this.externalFiles == null) {
@@ -3116,10 +3130,52 @@
}
}
+ /**
+ * Returns the cached value for whether the file referred to by <code>path</code> exists
+ * and is a file, as determined by the return value of {@link File#isFile()}.
+ */
public boolean isExternalFile(IPath path) {
return this.externalFiles != null && this.externalFiles.contains(path);
}
+ /**
+ * Removes the cached state of a single entry in the externalFiles cache.
+ */
+ public void clearExternalFileState(IPath path) {
+ if (this.externalFiles != null) {
+ this.externalFiles.remove(path);
+ }
+ }
+
+ /**
+ * Resets the entire externalFiles cache.
+ */
+ public void resetExternalFilesCache() {
+ if (this.externalFiles != null) {
+ this.externalFiles.clear();
+ }
+ }
+
+ /**
+ * Returns whether the provided {@link IPath} appears to be an external file,
+ * which is true if the path does not represent an internal resource, does not
+ * exist on the file system, and does have a file extension (this is the definition
+ * provided by {@link ExternalFoldersManager#isExternalFolderPath}).
+ */
+ public boolean isAssumedExternalFile(IPath path) {
+ if (this.assumedExternalFiles == null) {
+ return false;
+ }
+ return this.assumedExternalFiles.contains(path);
+ }
+
+ /**
+ * Adds the provided {@link IPath} to the list of assumed external files.
+ */
+ public void addAssumedExternalFile(IPath path) {
+ this.assumedExternalFiles.add(path);
+ }
+
public void setClasspathBeingResolved(IJavaProject project, boolean classpathIsResolved) {
if (classpathIsResolved) {
getClasspathBeingResolved().add(project);
@@ -3141,7 +3197,7 @@
}
} catch (IOException e) {
if (cacheFile.exists())
- Util.log(e, "Unable to read non-chaining jar cache file"); //$NON-NLS-1$
+ Util.log(e, "Unable to read JavaModelManager " + cacheName + " file"); //$NON-NLS-1$ //$NON-NLS-2$
} finally {
if (in != null) {
try {
@@ -3190,6 +3246,8 @@
return this.invalidArchives;
else if (cacheName == EXTERNAL_FILES_CACHE)
return this.externalFiles;
+ else if (cacheName == ASSUMED_EXTERNAL_FILES_CACHE)
+ return this.assumedExternalFiles;
else
return null;
}
@@ -3934,6 +3992,8 @@
this.invalidArchives.clear();
if (this.externalFiles != null)
this.externalFiles.clear();
+ if (this.assumedExternalFiles != null)
+ this.assumedExternalFiles.clear();
}
/*
@@ -4283,6 +4343,7 @@
saveClasspathListCache(NON_CHAINING_JARS_CACHE);
saveClasspathListCache(INVALID_ARCHIVES_CACHE);
saveClasspathListCache(EXTERNAL_FILES_CACHE);
+ saveClasspathListCache(ASSUMED_EXTERNAL_FILES_CACHE);
// will need delta since this save (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38658)
context.needDelta();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocContents.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocContents.java
index 8bb3617..861d6d2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocContents.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocContents.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2013 IBM Corporation and others.
+ * Copyright (c) 2009, 2014 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
@@ -345,6 +345,9 @@
this.tempLastAnchorFoundIndex = this.unknownFormatLastAnchorFoundIndex;
range = computeChildRange(anchor, this.indexOfFieldsBottom);
+ if (range == null) {
+ range = computeChildRange(getJavadoc8Anchor(anchor), this.indexOfAllMethodsBottom);
+ }
this.unknownFormatLastAnchorFoundIndex = this.tempLastAnchorFoundIndex;
this.unknownFormatAnchorIndexesCount = this.tempAnchorIndexesCount;
@@ -361,6 +364,9 @@
this.tempLastAnchorFoundIndex = this.methodLastAnchorFoundIndex;
range = computeChildRange(anchor, this.indexOfAllMethodsBottom);
+ if (range == null) {
+ range = computeChildRange(getJavadoc8Anchor(anchor), this.indexOfAllMethodsBottom);
+ }
this.methodLastAnchorFoundIndex = this.tempLastAnchorFoundIndex;
this.methodAnchorIndexesCount = this.tempAnchorIndexesCount;
@@ -370,6 +376,35 @@
return range;
}
+ private static char[] getJavadoc8Anchor(char[] anchor) {
+ // fix for bug 432284: [1.8] Javadoc-8-style anchors not found by IMethod#getAttachedJavadoc(..)
+ char[] anchor8 = new char[anchor.length];
+ int i8 = 0;
+ for (int i = 0; i < anchor.length; i++) {
+ char ch = anchor[i];
+ switch (ch) {
+ case '(':
+ case ')':
+ case ',':
+ anchor8[i8++] = '-';
+ break;
+ case '[':
+ anchor8[i8++] = ':';
+ anchor8[i8++] = 'A';
+ break;
+ case ' ': // handled by preceding ','
+ case ']': // handled by preceding '['
+ break;
+ default:
+ anchor8[i8++] = ch;
+ }
+ }
+ if (i8 != anchor.length) {
+ anchor8 = CharOperation.subarray(anchor8, 0, i8);
+ }
+ return anchor8;
+ }
+
private String computeMethodAnchorPrefixEnd(BinaryMethod method) throws JavaModelException {
String typeQualifiedName = null;
if (this.type.isMember()) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaExpression.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaExpression.java
index 4831432..327b07b 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaExpression.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaExpression.java
@@ -14,6 +14,7 @@
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.WorkingCopyOwner;
@@ -35,20 +36,20 @@
// Construction from AST node
- public LambdaExpression(JavaElement parent, org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambdaExpression) {
- super(parent, new String("Lambda(") + new String(lambdaExpression.resolvedType.sourceName()) + ')'); //$NON-NLS-1$
+ LambdaExpression(JavaElement parent, org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambdaExpression) {
+ super(parent, new String(CharOperation.NO_CHAR));
this.sourceStart = lambdaExpression.sourceStart;
this.sourceEnd = lambdaExpression.sourceEnd;
this.arrowPosition = lambdaExpression.arrowPosition;
this.interphase = new String(CharOperation.replaceOnCopy(lambdaExpression.resolvedType.genericTypeSignature(), '/', '.'));
this.elementInfo = makeTypeElementInfo(this, this.interphase, this.sourceStart, this.sourceEnd, this.arrowPosition);
- this.lambdaMethod = LambdaMethod.make(this, lambdaExpression);
+ this.lambdaMethod = LambdaFactory.createLambdaMethod(this, lambdaExpression);
this.elementInfo.children = new IJavaElement[] { this.lambdaMethod };
}
// Construction from memento
- public LambdaExpression(JavaElement parent, String name, String interphase, int sourceStart, int sourceEnd, int arrowPosition) {
- super(parent, name);
+ LambdaExpression(JavaElement parent, String interphase, int sourceStart, int sourceEnd, int arrowPosition) {
+ super(parent, new String(CharOperation.NO_CHAR));
this.sourceStart = sourceStart;
this.sourceEnd = sourceEnd;
this.arrowPosition = arrowPosition;
@@ -58,8 +59,8 @@
}
// Construction from subtypes.
- public LambdaExpression(JavaElement parent, String name, String interphase, int sourceStart, int sourceEnd, int arrowPosition, LambdaMethod lambdaMethod) {
- super(parent, name);
+ LambdaExpression(JavaElement parent, String interphase, int sourceStart, int sourceEnd, int arrowPosition, LambdaMethod lambdaMethod) {
+ super(parent, new String(CharOperation.NO_CHAR));
this.sourceStart = sourceStart;
this.sourceEnd = sourceEnd;
this.arrowPosition = arrowPosition;
@@ -104,9 +105,9 @@
LambdaExpression that = (LambdaExpression) o;
if (this.sourceStart != that.sourceStart)
return false;
- CompilationUnit thisCU = (CompilationUnit) this.getCompilationUnit();
- CompilationUnit thatCU = (CompilationUnit) that.getCompilationUnit();
- return thisCU.getElementName().equals(thatCU.getElementName()) && thisCU.parent.equals(thatCU.parent);
+ ITypeRoot thisTR = this.getTypeRoot();
+ ITypeRoot thatTR = that.getTypeRoot();
+ return thisTR.getElementName().equals(thatTR.getElementName()) && thisTR.getParent().equals(thatTR.getParent());
}
return false;
}
@@ -127,15 +128,16 @@
* @see JavaElement#getHandleMemento(StringBuffer)
*/
protected void getHandleMemento(StringBuffer buff) {
- getHandleMemento(buff, true);
+ getHandleMemento(buff, true, true);
+ // lambda method and lambda expression cannot share the same memento - add a trailing discriminator.
+ appendEscapedDelimiter(buff, getHandleMementoDelimiter());
}
- protected void getHandleMemento(StringBuffer buff, boolean memoizeParent) {
- if (memoizeParent)
+ protected void getHandleMemento(StringBuffer buff, boolean serializeParent, boolean serializeChild) {
+ if (serializeParent)
((JavaElement)getParent()).getHandleMemento(buff);
- buff.append(getHandleMementoDelimiter());
- escapeMementoName(buff, this.name);
- buff.append(JEM_STRING);
+ appendEscapedDelimiter(buff, getHandleMementoDelimiter());
+ appendEscapedDelimiter(buff, JEM_STRING);
escapeMementoName(buff, this.interphase);
buff.append(JEM_COUNT);
buff.append(this.sourceStart);
@@ -143,6 +145,8 @@
buff.append(this.sourceEnd);
buff.append(JEM_COUNT);
buff.append(this.arrowPosition);
+ if (serializeChild)
+ this.lambdaMethod.getHandleMemento(buff, false);
}
public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner workingCopyOwner) {
@@ -168,14 +172,24 @@
String returnType = memento.nextToken();
if (!memento.hasMoreTokens() || memento.nextToken().charAt(0) != JEM_STRING) return this;
String key = memento.nextToken();
- this.lambdaMethod = LambdaMethod.make(this, selector, key, this.sourceStart, this.sourceEnd, this.arrowPosition, parameterTypes, parameterNames, returnType);
+ this.lambdaMethod = LambdaFactory.createLambdaMethod(this, selector, key, this.sourceStart, this.sourceEnd, this.arrowPosition, parameterTypes, parameterNames, returnType);
ILocalVariable [] parameters = new ILocalVariable[length];
for (int i = 0; i < length; i++) {
parameters[i] = (ILocalVariable) this.lambdaMethod.getHandleFromMemento(memento, workingCopyOwner);
}
this.lambdaMethod.elementInfo.arguments = parameters;
this.elementInfo.children = new IJavaElement[] { this.lambdaMethod };
- return this.lambdaMethod;
+ if (!memento.hasMoreTokens())
+ return this.lambdaMethod;
+ switch (memento.nextToken().charAt(0)) {
+ case JEM_LAMBDA_METHOD:
+ if (!memento.hasMoreTokens())
+ return this.lambdaMethod;
+ return this.lambdaMethod.getHandleFromMemento(memento, workingCopyOwner);
+ case JEM_LAMBDA_EXPRESSION:
+ default:
+ return this;
+ }
}
public IJavaElement[] getChildren() throws JavaModelException {
@@ -196,6 +210,23 @@
}
@Override
+ public boolean isLambda() {
+ return true;
+ }
+
+ @Override
+ public boolean isAnonymous() {
+ return false;
+ }
+
+ public void toStringName(StringBuffer buffer) {
+ super.toStringName(buffer);
+ buffer.append("<lambda #"); //$NON-NLS-1$
+ buffer.append(this.occurrenceCount);
+ buffer.append(">"); //$NON-NLS-1$
+ }
+
+ @Override
public IJavaElement getPrimaryElement(boolean checkOwner) {
if (checkOwner) {
CompilationUnit cu = (CompilationUnit)getAncestor(COMPILATION_UNIT);
@@ -205,8 +236,7 @@
if (primaryParent instanceof JavaElement) {
JavaElement ancestor = (JavaElement) primaryParent;
StringBuffer buffer = new StringBuffer(32);
- getHandleMemento(buffer, false);
- this.lambdaMethod.getHandleMemento(buffer, false);
+ getHandleMemento(buffer, false, true);
String memento = buffer.toString();
return ancestor.getHandleFromMemento(new MementoTokenizer(memento), DefaultWorkingCopyOwner.PRIMARY).getParent();
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaFactory.java
new file mode 100644
index 0000000..ff8bc0e
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaFactory.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2014 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
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.jdt.internal.core;
+
+import org.eclipse.jdt.core.ILocalVariable;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+
+public class LambdaFactory {
+
+ public static LambdaExpression createLambdaExpression(JavaElement parent, org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambdaExpression) {
+ if (isBinaryMember(parent)){
+ return new BinaryLambdaExpression(parent, lambdaExpression);
+ } else {
+ return new LambdaExpression(parent, lambdaExpression);
+ }
+ }
+
+ public static LambdaExpression createLambdaExpression(JavaElement parent, String interphase, int sourceStart, int sourceEnd, int arrowPosition) {
+ if (isBinaryMember(parent)){
+ return new BinaryLambdaExpression(parent, interphase, sourceStart, sourceEnd, arrowPosition);
+ } else {
+ return new LambdaExpression(parent, interphase, sourceStart, sourceEnd, arrowPosition);
+ }
+ }
+
+ public static LambdaMethod createLambdaMethod(JavaElement parent, org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambdaExpression) {
+ int length;
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ String [] parameterTypes = new String[length = lambdaExpression.descriptor.parameters.length];
+ for (int i = 0; i < length; i++)
+ parameterTypes[i] = getTypeSignature(manager, lambdaExpression.descriptor.parameters[i]);
+ String [] parameterNames = new String[length];
+ for (int i = 0; i < length; i++)
+ parameterNames[i] = manager.intern(new String(lambdaExpression.arguments[i].name));
+ String returnType = getTypeSignature(manager, lambdaExpression.descriptor.returnType);
+ String selector = manager.intern(new String(lambdaExpression.descriptor.selector));
+ String key = new String(lambdaExpression.descriptor.computeUniqueKey());
+ LambdaMethod lambdaMethod = createLambdaMethod(parent, selector, key, lambdaExpression.sourceStart, lambdaExpression.sourceEnd, lambdaExpression.arrowPosition, parameterTypes, parameterNames, returnType);
+ ILocalVariable [] parameters = new ILocalVariable[length = lambdaExpression.arguments.length];
+ for (int i = 0; i < length; i++) {
+ Argument argument = lambdaExpression.arguments[i];
+ String signature = manager.intern(new String(lambdaExpression.descriptor.parameters[i].signature()));
+ parameters[i] = new LocalVariable(
+ lambdaMethod,
+ new String(argument.name),
+ argument.declarationSourceStart,
+ argument.declarationSourceEnd,
+ argument.sourceStart,
+ argument.sourceEnd,
+ signature,
+ null, // we are not hooking up argument.annotations ATM,
+ argument.modifiers,
+ true);
+ }
+ lambdaMethod.elementInfo.arguments = parameters;
+ return lambdaMethod;
+ }
+
+ public static LambdaMethod createLambdaMethod(JavaElement parent, String selector, String key, int sourceStart, int sourceEnd, int arrowPosition, String [] parameterTypes, String [] parameterNames, String returnType) {
+ SourceMethodInfo info = null;
+ boolean isBinary = (parent instanceof BinaryLambdaExpression);
+ info = new SourceMethodInfo();
+ info.setSourceRangeStart(sourceStart);
+ info.setSourceRangeEnd(sourceEnd);
+ info.setFlags(0);
+ info.setNameSourceStart(sourceStart);
+ info.setNameSourceEnd(arrowPosition);
+ JavaModelManager manager = JavaModelManager.getJavaModelManager();
+ int length;
+ char[][] argumentNames = new char[length = parameterNames.length][];
+ for (int i = 0; i < length; i++)
+ argumentNames[i] = manager.intern(parameterNames[i].toCharArray());
+ info.setArgumentNames(argumentNames);
+ info.setReturnType(manager.intern(Signature.toCharArray(returnType.toCharArray())));
+ info.setExceptionTypeNames(CharOperation.NO_CHAR_CHAR);
+ info.arguments = null; // will be updated shortly, parent has to come into existence first.
+
+ return isBinary ? new BinaryLambdaMethod(parent, selector, key, sourceStart, parameterTypes, parameterNames, returnType, info) :
+ new LambdaMethod(parent, selector, key, sourceStart, parameterTypes, parameterNames, returnType, info);
+ }
+
+ private static String getTypeSignature(JavaModelManager manager, TypeBinding type) {
+ char[] signature = type.genericTypeSignature();
+ signature = CharOperation.replaceOnCopy(signature, '/', '.');
+ return manager.intern(new String(signature));
+ }
+
+ private static boolean isBinaryMember(JavaElement element) {
+ return element instanceof BinaryMember;
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaMethod.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaMethod.java
index 40afa74..7d56d35 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaMethod.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LambdaMethod.java
@@ -16,10 +16,7 @@
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
-import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.core.util.Util;
public class LambdaMethod extends SourceMethod {
@@ -30,7 +27,7 @@
SourceMethodElementInfo elementInfo;
private String key;
- public LambdaMethod(JavaElement parent, String name, String key, int sourceStart, String [] parameterTypes, String [] parameterNames, String returnType, SourceMethodElementInfo elementInfo) {
+ LambdaMethod(JavaElement parent, String name, String key, int sourceStart, String [] parameterTypes, String [] parameterNames, String returnType, SourceMethodElementInfo elementInfo) {
super(parent, name, parameterTypes);
this.sourceStart = sourceStart;
this.parameterNameStrings = parameterNames;
@@ -39,64 +36,6 @@
this.key = key;
}
- public static LambdaMethod make(JavaElement parent, org.eclipse.jdt.internal.compiler.ast.LambdaExpression lambdaExpression) {
- int length;
- JavaModelManager manager = JavaModelManager.getJavaModelManager();
- String [] parameterTypes = new String[length = lambdaExpression.descriptor.parameters.length];
- for (int i = 0; i < length; i++)
- parameterTypes[i] = getTypeSignature(manager, lambdaExpression.descriptor.parameters[i]);
- String [] parameterNames = new String[length];
- for (int i = 0; i < length; i++)
- parameterNames[i] = manager.intern(new String(lambdaExpression.arguments[i].name));
- String returnType = getTypeSignature(manager, lambdaExpression.descriptor.returnType);
- String selector = manager.intern(new String(lambdaExpression.descriptor.selector));
- String key = new String(lambdaExpression.descriptor.computeUniqueKey());
- LambdaMethod lambdaMethod = make(parent, selector, key, lambdaExpression.sourceStart, lambdaExpression.sourceEnd, lambdaExpression.arrowPosition, parameterTypes, parameterNames, returnType);
- ILocalVariable [] parameters = new ILocalVariable[length = lambdaExpression.arguments.length];
- for (int i = 0; i < length; i++) {
- Argument argument = lambdaExpression.arguments[i];
- String signature = manager.intern(new String(lambdaExpression.descriptor.parameters[i].signature()));
- parameters[i] = new LocalVariable(
- lambdaMethod,
- new String(argument.name),
- argument.declarationSourceStart,
- argument.declarationSourceEnd,
- argument.sourceStart,
- argument.sourceEnd,
- signature,
- null, // we are not hooking up argument.annotations ATM,
- argument.modifiers,
- true);
- }
- lambdaMethod.elementInfo.arguments = parameters;
- return lambdaMethod;
- }
-
- public static LambdaMethod make(JavaElement parent, String selector, String key, int sourceStart, int sourceEnd, int arrowPosition, String [] parameterTypes, String [] parameterNames, String returnType) {
- SourceMethodInfo info = new SourceMethodInfo();
- info.setSourceRangeStart(sourceStart);
- info.setSourceRangeEnd(sourceEnd);
- info.setFlags(0);
- info.setNameSourceStart(sourceStart);
- info.setNameSourceEnd(arrowPosition);
- JavaModelManager manager = JavaModelManager.getJavaModelManager();
- int length;
- char[][] argumentNames = new char[length = parameterNames.length][];
- for (int i = 0; i < length; i++)
- argumentNames[i] = manager.intern(parameterNames[i].toCharArray());
- info.setArgumentNames(argumentNames);
- info.setReturnType(manager.intern(Signature.toCharArray(returnType.toCharArray())));
- info.setExceptionTypeNames(CharOperation.NO_CHAR_CHAR);
- info.arguments = null; // will be updated shortly, parent has to come into existence first.
- return new LambdaMethod(parent, selector, key, sourceStart, parameterTypes, parameterNames, returnType, info);
- }
-
- public static String getTypeSignature(JavaModelManager manager, TypeBinding type) {
- char[] signature = type.genericTypeSignature();
- signature = CharOperation.replaceOnCopy(signature, '/', '.');
- return manager.intern(new String(signature));
- }
-
/**
* @see IMethod
*/
@@ -130,23 +69,23 @@
return this.elementInfo;
}
- public void getHandleMemento(StringBuffer buff, boolean memoizeParent) {
- if (memoizeParent)
- ((JavaElement) getParent()).getHandleMemento(buff);
- char delimiter = getHandleMementoDelimiter();
- buff.append(delimiter);
+ public void getHandleMemento(StringBuffer buff, boolean serializeParent) {
+ if (serializeParent) {
+ ((LambdaExpression) getParent()).getHandleMemento(buff, true, false);
+ }
+ appendEscapedDelimiter(buff, getHandleMementoDelimiter());
escapeMementoName(buff, getElementName());
buff.append(JEM_COUNT);
buff.append(this.parameterTypes.length);
for (int i = 0, length = this.parameterTypes.length; i < length; i++) {
- buff.append(JEM_STRING);
+ appendEscapedDelimiter(buff, JEM_STRING);
escapeMementoName(buff, this.parameterTypes[i]);
- buff.append(JEM_STRING);
+ appendEscapedDelimiter(buff, JEM_STRING);
escapeMementoName(buff, this.parameterNameStrings[i]);
}
- buff.append(JEM_STRING);
+ appendEscapedDelimiter(buff, JEM_STRING);
escapeMementoName(buff, this.returnTypeString);
- buff.append(JEM_STRING);
+ appendEscapedDelimiter(buff, JEM_STRING);
escapeMementoName(buff, this.key);
ILocalVariable[] arguments = this.elementInfo.arguments;
for (int i = 0, length = arguments.length; i < length; i++) {
@@ -156,6 +95,8 @@
}
public void getHandleMemento(StringBuffer buff) {
getHandleMemento(buff, true);
+ // lambda method and lambda expression cannot share the same memento - add a trailing discriminator.
+ appendEscapedDelimiter(buff, getHandleMementoDelimiter());
}
protected char getHandleMementoDelimiter() {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
index 38e4c04..10ce6ea 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Member.java
@@ -173,8 +173,6 @@
case JEM_COUNT:
return getHandleUpdatingCountFromMemento(memento, workingCopyOwner);
case JEM_LAMBDA_EXPRESSION:
- if (!memento.hasMoreTokens()) return this;
- String name = memento.nextToken();
if (!memento.hasMoreTokens() || memento.nextToken() != MementoTokenizer.STRING)
return this;
if (!memento.hasMoreTokens()) return this;
@@ -188,7 +186,7 @@
if (!memento.hasMoreTokens() || memento.nextToken() != MementoTokenizer.COUNT)
return this;
int arrowPosition = Integer.parseInt(memento.nextToken());
- LambdaExpression expression = new LambdaExpression(this, name, interphase, sourceStart, sourceEnd, arrowPosition);
+ LambdaExpression expression = LambdaFactory.createLambdaExpression(this, interphase, sourceStart, sourceEnd, arrowPosition);
if (!memento.hasMoreTokens() || (token = memento.nextToken()) != MementoTokenizer.LAMBDA_METHOD)
return expression;
return expression.getHandleFromMemento(token, memento, workingCopyOwner);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
index 46f8740..80b108a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -660,7 +660,7 @@
IJavaProject javaProject = null;
Answer suggestedAnswer = null;
for (int i= 0; i < length; i++) {
- type = findType(typeName, packages[i], partialMatch, acceptFlags);
+ type = findType(typeName, packages[i], partialMatch, acceptFlags, waitForIndexes, considerSecondaryTypes);
if (type != null) {
AccessRestriction accessRestriction = null;
if (checkRestrictions) {
@@ -761,10 +761,16 @@
* @see #ACCEPT_ENUMS
* @see #ACCEPT_ANNOTATIONS
*/
- public IType findType(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, boolean considerSecondaryTypes) {
- IType type = findType(name, pkg, partialMatch, acceptFlags);
+ public IType findType(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, boolean waitForIndices, boolean considerSecondaryTypes) {
+ if (pkg == null)
+ return null;
+
+ SingleTypeRequestor typeRequestor = new SingleTypeRequestor();
+ seekTypes(name, pkg, partialMatch, acceptFlags, typeRequestor, considerSecondaryTypes);
+ IType type = typeRequestor.getType();
+
if (type == null && considerSecondaryTypes) {
- type = findSecondaryType(pkg.getElementName(), name, pkg.getJavaProject(), false, null);
+ type = findSecondaryType(pkg.getElementName(), name, pkg.getJavaProject(), waitForIndices, null);
}
return type;
}
@@ -795,7 +801,7 @@
// Return first found (ignore duplicates).
SingleTypeRequestor typeRequestor = new SingleTypeRequestor();
- seekTypes(name, pkg, partialMatch, acceptFlags, typeRequestor);
+ seekTypes(name, pkg, partialMatch, acceptFlags, typeRequestor, false);
return typeRequestor.getType();
}
@@ -825,6 +831,9 @@
}
public Answer findType(String name, boolean partialMatch, int acceptFlags, boolean considerSecondaryTypes, boolean waitForIndexes, boolean checkRestrictions, IProgressMonitor monitor) {
int index= name.lastIndexOf('.');
+ if (index == 0) {
+ return null; // bug 377710 - e.g. ".Foo" (no package, but not "default" package)
+ }
String className= null, packageName= null;
if (index == -1) {
packageName= IPackageFragment.DEFAULT_PACKAGE_NAME;
@@ -949,6 +958,10 @@
}
}
+ public void seekTypes(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
+ seekTypes(name, pkg, partialMatch, acceptFlags, requestor, true);
+ }
+
/**
* Notifies the given requestor of all types (classes and interfaces) in the
* given package fragment with the given (unqualified) name.
@@ -969,7 +982,7 @@
* @see #ACCEPT_ENUMS
* @see #ACCEPT_ANNOTATIONS
*/
- public void seekTypes(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor) {
+ public void seekTypes(String name, IPackageFragment pkg, boolean partialMatch, int acceptFlags, IJavaElementRequestor requestor, boolean considerSecondaryTypes) {
/* if (VERBOSE) {
Util.verbose(" SEEKING TYPES"); //$NON-NLS-1$
Util.verbose(" -> name: " + name); //$NON-NLS-1$
@@ -995,7 +1008,7 @@
topLevelTypeName = firstDot == -1 ? matchName : matchName.substring(0, firstDot);
}
if (this.typesInWorkingCopies != null) {
- if (seekTypesInWorkingCopies(matchName, pkg, firstDot, partialMatch, topLevelTypeName, acceptFlags, requestor))
+ if (seekTypesInWorkingCopies(matchName, pkg, firstDot, partialMatch, topLevelTypeName, acceptFlags, requestor, considerSecondaryTypes))
return;
}
@@ -1150,6 +1163,24 @@
}
}
+ private boolean isPrimaryType(String name, IType type, boolean partialMatch) {
+ /*
+ * Please have a look at: NameLookup#NameLookup
+ * The HashTable this.typesInWorkingCopies contains values which are HashTables themselves.
+ * The values of these HashTables are either of IType or IType[].
+ * These values are types belonging to a compilation unit. Please check:
+ * CompilationUnit#getTypes().
+ * Therefore the parents of these types would be compilation units.
+ */
+ ICompilationUnit cu = (ICompilationUnit) type.getParent();
+ String cuName = cu.getElementName().substring(0, cu.getElementName().lastIndexOf('.'));
+ if (partialMatch) {
+ return cuName.regionMatches(0, name, 0, name.length());
+ } else {
+ return cuName.equals(name);
+ }
+ }
+
/**
* Notifies the given requestor of all types (classes and interfaces) in the
* given type with the given (possibly qualified) name. Checks
@@ -1215,7 +1246,8 @@
boolean partialMatch,
String topLevelTypeName,
int acceptFlags,
- IJavaElementRequestor requestor) {
+ IJavaElementRequestor requestor,
+ boolean considerSecondaryTypes) {
if (!partialMatch) {
HashMap typeMap = (HashMap) (this.typesInWorkingCopies == null ? null : this.typesInWorkingCopies.get(pkg));
@@ -1223,6 +1255,8 @@
Object object = typeMap.get(topLevelTypeName);
if (object instanceof IType) {
IType type = getMemberType((IType) object, name, firstDot);
+ if (!considerSecondaryTypes && !isPrimaryType(name, (IType) object, false))
+ return false;
if (acceptType(type, acceptFlags, true/*a source type*/)) {
requestor.acceptType(type);
return true; // don't continue with compilation unit
@@ -1256,6 +1290,8 @@
return false;
Object object = iterator.next();
if (object instanceof IType) {
+ if (!considerSecondaryTypes && !isPrimaryType(name, (IType) object, true))
+ continue;
seekTypesInTopLevelType(name, firstDot, (IType) object, requestor, acceptFlags);
} else if (object instanceof IType[]) {
IType[] topLevelTypes = (IType[]) object;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
index 9db976f..9ccad47 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java
@@ -491,7 +491,7 @@
pathBuffer.append(packPath).append('/').append(JavadocConstants.PACKAGE_FILE_NAME);
if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
- String contents = getURLContents(String.valueOf(pathBuffer));
+ String contents = getURLContents(baseLocation, String.valueOf(pathBuffer));
if (monitor != null && monitor.isCanceled()) throw new OperationCanceledException();
if (contents == null) return null;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedLambdaExpression.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedLambdaExpression.java
index a687dc5..0fa4c89 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedLambdaExpression.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ResolvedLambdaExpression.java
@@ -18,7 +18,7 @@
LambdaExpression unresolved;
public ResolvedLambdaExpression(JavaElement parent, LambdaExpression unresolved, String uniqueKey) {
- super(parent, unresolved.name, unresolved.interphase, unresolved.sourceStart, unresolved.sourceEnd, unresolved.arrowPosition, unresolved.lambdaMethod);
+ super(parent, unresolved.interphase, unresolved.sourceStart, unresolved.sourceEnd, unresolved.arrowPosition, unresolved.lambdaMethod);
this.uniqueKey = uniqueKey;
this.unresolved = unresolved;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
index aae1dd9..8c7ebc2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SelectionRequestor.java
@@ -863,7 +863,7 @@
IJavaElement parent = findLocalElement(pos, scope.enclosingMethodScope());
LambdaExpression expression = (LambdaExpression) scope.originalReferenceContext();
if (expression != null && expression.resolvedType != null && expression.resolvedType.isValidBinding()) {
- org.eclipse.jdt.internal.core.LambdaExpression lambdaElement = new org.eclipse.jdt.internal.core.LambdaExpression((JavaElement) parent, expression);
+ org.eclipse.jdt.internal.core.LambdaExpression lambdaElement = LambdaFactory.createLambdaExpression((JavaElement) parent, expression);
return lambdaElement.getMethod();
}
return parent;
@@ -941,7 +941,7 @@
false);
// iterate type lookup in each package fragment
for (int i = 0, length = pkgs == null ? 0 : pkgs.length; i < length; i++) {
- type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags, true/*consider secondary types*/);
+ type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags, false, true/*consider secondary types*/);
if (type != null) break;
}
if (type == null) {
@@ -1021,7 +1021,7 @@
false);
// iterate type lookup in each package fragment
for (int i = 0, length = pkgs == null ? 0 : pkgs.length; i < length; i++) {
- type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags, true/*consider secondary types*/);
+ type= this.nameLookup.findType(new String(typeName), pkgs[i], false, acceptFlags, false, true/*consider secondary types*/);
if (type != null) break;
}
if (type == null) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
index 7947315..d00f35f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceType.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -841,8 +841,7 @@
protected void toStringInfo(int tab, StringBuffer buffer, Object info, boolean showResolvedInfo) {
buffer.append(tabString(tab));
if (info == null) {
- String elementName = getElementName();
- if (elementName.length() == 0) {
+ if (isAnonymous()) {
buffer.append("<anonymous #"); //$NON-NLS-1$
buffer.append(this.occurrenceCount);
buffer.append(">"); //$NON-NLS-1$
@@ -851,8 +850,7 @@
}
buffer.append(" (not open)"); //$NON-NLS-1$
} else if (info == NO_INFO) {
- String elementName = getElementName();
- if (elementName.length() == 0) {
+ if (isAnonymous()) {
buffer.append("<anonymous #"); //$NON-NLS-1$
buffer.append(this.occurrenceCount);
buffer.append(">"); //$NON-NLS-1$
@@ -870,8 +868,7 @@
} else {
buffer.append("class "); //$NON-NLS-1$
}
- String elementName = getElementName();
- if (elementName.length() == 0) {
+ if (isAnonymous()) {
buffer.append("<anonymous #"); //$NON-NLS-1$
buffer.append(this.occurrenceCount);
buffer.append(">"); //$NON-NLS-1$
@@ -883,4 +880,8 @@
}
}
}
+@Override
+public boolean isLambda() {
+ return false;
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
index b29bfff..87929f5 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceTypeElementInfo.java
@@ -170,7 +170,7 @@
* @see ISourceType
*/
public char[][] getInterfaceNames() {
- if (this.handle.getElementName().length() == 0) { // if anonymous type
+ if (isAnonymous()) { // if anonymous type
return null;
}
return this.superInterfaceNames;
@@ -251,7 +251,7 @@
* @see ISourceType
*/
public char[] getSuperclassName() {
- if (this.handle.getElementName().length() == 0) { // if anonymous type
+ if (isAnonymous()) { // if anonymous type
char[][] interfaceNames = this.superInterfaceNames;
if (interfaceNames != null && interfaceNames.length > 0) {
return interfaceNames[0];
@@ -287,6 +287,15 @@
public boolean isBinaryType() {
return false;
}
+
+@Override
+public boolean isAnonymous() {
+ try {
+ return this.handle.isAnonymous();
+ } catch (JavaModelException e) {
+ return false;
+ }
+}
/*
* Returns whether the source type is an anonymous type of a member type.
*/
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
index 8c858f7..09711da 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Terry Parker <tparker@google.com> - [performance] Low hit rates in JavaModel caches - https://bugs.eclipse.org/421165
*******************************************************************************/
package org.eclipse.jdt.internal.core.builder;
@@ -611,7 +612,6 @@
// Flush the existing external files cache if this is the beginning of a build cycle
String projectName = this.currentProject.getName();
if (builtProjects == null || builtProjects.contains(projectName)) {
- JavaModel.flushExternalFileCache();
builtProjects = new ArrayList();
}
builtProjects.add(projectName);
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 37c881b..09df4a7 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
@@ -231,7 +231,7 @@
separator = '/';
} else if (type instanceof ISourceType) {
ISourceType sourceType = (ISourceType)type;
- if (sourceType.getName().length == 0) { // if anonymous type
+ if (sourceType.isAnonymous()) { // if anonymous type
if (typeBinding.superInterfaces() != null && typeBinding.superInterfaces().length > 0) {
superInterfaceNames = new char[][] {sourceType.getSuperclassName()};
} else {
@@ -246,7 +246,7 @@
separator = '.';
} else if (type instanceof HierarchyType) {
HierarchyType hierarchyType = (HierarchyType)type;
- if (hierarchyType.name.length == 0) { // if anonymous type
+ if (hierarchyType.isAnonymous()) { // if anonymous type
if (typeBinding.superInterfaces() != null && typeBinding.superInterfaces().length > 0) {
superInterfaceNames = new char[][] {hierarchyType.superclassName};
} else {
@@ -404,7 +404,12 @@
}
} else {
if (typeBinding == null) return;
-
+ boolean isAnonymous = false;
+ try {
+ isAnonymous = type.isAnonymous();
+ } catch(JavaModelException jme) {
+ // Ignore
+ }
if (typeBinding instanceof SourceTypeBinding) {
TypeDeclaration typeDeclaration = ((SourceTypeBinding)typeBinding).scope.referenceType();
@@ -439,7 +444,8 @@
typeDeclaration.name,
typeDeclaration.binding.modifiers,
superclassName,
- superInterfaceNames);
+ superInterfaceNames,
+ isAnonymous);
remember(hierarchyType, typeDeclaration.binding);
} else {
HierarchyType hierarchyType = new HierarchyType(
@@ -447,7 +453,8 @@
typeBinding.sourceName(),
typeBinding.modifiers,
typeBinding.superclass().sourceName(),
- new char [][] { typeBinding.superInterfaces()[0].sourceName() });
+ new char [][] { typeBinding.superInterfaces()[0].sourceName() },
+ isAnonymous);
remember(hierarchyType, typeBinding);
}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
index ef674ae..87effe1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyType.java
@@ -25,19 +25,22 @@
public int modifiers;
public char[] superclassName;
public char[][] superInterfaceNames;
+ public boolean anonymous;
public HierarchyType(
IType typeHandle,
char[] name,
int modifiers,
char[] superclassName,
- char[][] superInterfaceNames) {
+ char[][] superInterfaceNames,
+ boolean anonymous) {
this.typeHandle = typeHandle;
this.name = name;
this.modifiers = modifiers;
this.superclassName = superclassName;
this.superInterfaceNames = superInterfaceNames;
+ this.anonymous = anonymous;
}
/**
* @see org.eclipse.jdt.internal.compiler.env.IDependent#getFileName()
@@ -60,4 +63,10 @@
public boolean isBinaryType() {
return false;
}
+/**
+ * Answer whether the receiver is an anonymous type
+ */
+public boolean isAnonymous() {
+ return this.anonymous;
+}
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
index 21cf02f..4e67ba2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -1187,7 +1187,7 @@
disassemble(enclosingMethodAttribute, buffer, lineSeparator, 0);
}
if (bootstrapMethods != null) {
- disassemble((IBootstrapMethodsAttribute) bootstrapMethods, buffer, lineSeparator, 0);
+ disassemble((IBootstrapMethodsAttribute) bootstrapMethods, buffer, lineSeparator, 0, classFileReader.getConstantPool());
}
if (checkMode(mode, SYSTEM)) {
if (runtimeVisibleAnnotationsAttribute != null) {
@@ -1572,6 +1572,80 @@
}
}
+ private String bootstrapMethodDescription(IBootstrapMethodsEntry entry, IConstantPool constantPool) {
+ // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
+ // The BootstrapMethods attribute records bootstrap method specifiers referenced by invokedynamic instructions.
+ // The value of the bootstrap_method_ref item must be a valid index into the constant_pool table. The constant_pool entry at that index must be a CONSTANT_MethodHandle_info structure (�4.4.8).
+ // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.8
+ // constantpoolentry.getKind() = IConstantPoolConstant.CONSTANT_MethodHandle
+
+ ConstantPoolEntry2 constantPoolEntry2 = (ConstantPoolEntry2) constantPool.decodeEntry(entry.getBootstrapMethodReference());
+
+ // The reference_kind item of the CONSTANT_MethodHandle_info structure should have the value 6 (REF_invokeStatic) or 8 (REF_newInvokeSpecial)
+ // (�5.4.3.5) or else invocation of the bootstrap method handle during call site specifier resolution for an invokedynamic instruction will complete abruptly.
+ // If the value of the reference_kind item is 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 7 (REF_invokeSpecial),
+ // or 9 (REF_invokeInterface), the name of the method represented by a CONSTANT_Methodref_info structure must not be <init> or <clinit>.
+
+ if (constantPoolEntry2.getReferenceKind() != 6)
+ return null;
+ ConstantPoolEntry constantPoolEntry = (ConstantPoolEntry) constantPool.decodeEntry(constantPoolEntry2.getReferenceIndex());
+ StringBuilder builder = new StringBuilder();
+ //String[] methodMsg = methodDescription(constantPoolEntry);
+ builder.append(Messages.bind("invokestatic {0}.{1}:{2}", methodDescription(constantPoolEntry))); //$NON-NLS-1$
+ return builder.toString();
+ }
+
+ private String[] bootstrapArgumentsDescription(IBootstrapMethodsEntry entry, IConstantPool constantPool) {
+ // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.21
+ // bootstrap_arguments
+ // Each entry in the bootstrap_arguments array must be a valid index into the constant_pool table.
+ // The constant_pool entry at that index must be a CONSTANT_String_info, CONSTANT_Class_info, CONSTANT_Integer_info
+ // CONSTANT_Long_info, CONSTANT_Float_info, CONSTANT_Double_info, CONSTANT_MethodHandle_info, or
+ // CONSTANT_MethodType_info structure (�4.4.3, �4.4.1, �4.4.4, �4.4.5), �4.4.8, �4.4.9).
+ if (entry.getBootstrapArguments().length == 0)
+ return null;
+ int[] bootstrapArguments = entry.getBootstrapArguments();
+ String[] arguments = new String[bootstrapArguments.length];
+ for (int i = 0, length = bootstrapArguments.length; i < length; i++) {
+ ConstantPoolEntry constantPoolEntry = (ConstantPoolEntry) constantPool.decodeEntry(bootstrapArguments[i]);
+ switch(constantPoolEntry.getKind()) {
+ case IConstantPoolConstant.CONSTANT_Integer:
+ arguments[i] = ((Integer) constantPoolEntry.getIntegerValue()).toString();
+ break;
+ case IConstantPoolConstant.CONSTANT_MethodHandle:
+ // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.8
+ // If the value of the reference_kind item is 5 (REF_invokeVirtual), 6 (REF_invokeStatic),
+ // 7 (REF_invokeSpecial), or 8 (REF_newInvokeSpecial), then the constant_pool entry at that
+ // index must be a CONSTANT_Methodref_info structure (�4.4.2) representing a class's method or
+ // constructor (�2.9) for which a method handle is to be created.
+ ConstantPoolEntry2 constantPoolEntry2 = (ConstantPoolEntry2) constantPoolEntry;
+ StringBuilder builder = new StringBuilder(10);
+ switch(constantPoolEntry2.getReferenceKind()) {
+ case IConstantPoolConstant.METHOD_TYPE_REF_InvokeStatic:
+ builder.append("invokestatic "); //$NON-NLS-1$
+ //$FALL-THROUGH$
+ case IConstantPoolConstant.METHOD_TYPE_REF_InvokeVirtual:
+ case IConstantPoolConstant.METHOD_TYPE_REF_NewInvokeSpecial:
+ constantPoolEntry = (ConstantPoolEntry) constantPool.decodeEntry(constantPoolEntry2.getReferenceIndex());
+ builder.append(Messages.bind("{0}.{1}:{2}", methodDescription(constantPoolEntry))); //$NON-NLS-1$
+ arguments[i] = builder.toString();
+ break;
+ }
+ break;
+ case IConstantPoolConstant.CONSTANT_MethodType:
+ arguments[i] = new String(((ConstantPoolEntry2) constantPoolEntry).getMethodDescriptor());
+ break;
+ }
+ }
+ return arguments;
+ }
+
+ private String[] methodDescription(IConstantPoolEntry constantPoolEntry) {
+ return new String[] { new String(constantPoolEntry.getClassName()),
+ new String(constantPoolEntry.getMethodName()),
+ new String(constantPoolEntry.getMethodDescriptor())};
+ }
+
private void disassemble(IConstantPool constantPool, StringBuffer buffer, String lineSeparator, int tabNumber) {
writeNewLine(buffer, lineSeparator, tabNumber);
int length = constantPool.getConstantPoolCount();
@@ -1582,6 +1656,7 @@
writeNewLine(buffer, lineSeparator, tabNumber + 1);
}
IConstantPoolEntry constantPoolEntry = constantPool.decodeEntry(i);
+ String[] methodDescription;
switch (constantPool.getEntryKind(i)) {
case IConstantPoolConstant.CONSTANT_Class :
buffer.append(
@@ -1625,15 +1700,14 @@
Integer.toString(constantPoolEntry.getIntegerValue())}));
break;
case IConstantPoolConstant.CONSTANT_InterfaceMethodref :
+ methodDescription = methodDescription(constantPoolEntry);
buffer.append(
Messages.bind(Messages.disassembler_constantpool_interfacemethodref,
new String[] {
Integer.toString(i),
Integer.toString(constantPoolEntry.getClassIndex()),
Integer.toString(constantPoolEntry.getNameAndTypeIndex()),
- new String(constantPoolEntry.getClassName()),
- new String(constantPoolEntry.getMethodName()),
- new String(constantPoolEntry.getMethodDescriptor())}));
+ methodDescription[0], methodDescription[1], methodDescription[2]}));
break;
case IConstantPoolConstant.CONSTANT_Long :
buffer.append(
@@ -1643,15 +1717,14 @@
Long.toString(constantPoolEntry.getLongValue())}));
break;
case IConstantPoolConstant.CONSTANT_Methodref :
+ methodDescription = methodDescription(constantPoolEntry);
buffer.append(
Messages.bind(Messages.disassembler_constantpool_methodref,
new String[] {
Integer.toString(i),
Integer.toString(constantPoolEntry.getClassIndex()),
Integer.toString(constantPoolEntry.getNameAndTypeIndex()),
- new String(constantPoolEntry.getClassName()),
- new String(constantPoolEntry.getMethodName()),
- new String(constantPoolEntry.getMethodDescriptor())}));
+ methodDescription[0], methodDescription[1], methodDescription[2]}));
break;
case IConstantPoolConstant.CONSTANT_NameAndType :
int nameIndex = constantPoolEntry.getNameAndTypeInfoNameIndex();
@@ -2019,7 +2092,7 @@
}
}
- private void disassemble(IBootstrapMethodsAttribute bootstrapMethodsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber) {
+ private void disassemble(IBootstrapMethodsAttribute bootstrapMethodsAttribute, StringBuffer buffer, String lineSeparator, int tabNumber, IConstantPool constantPool) {
writeNewLine(buffer, lineSeparator, tabNumber);
buffer.append(Messages.disassembler_bootstrapmethodattributesheader);
writeNewLine(buffer, lineSeparator, tabNumber + 1);
@@ -2031,32 +2104,33 @@
writeNewLine(buffer, lineSeparator, tabNumber + 1);
}
IBootstrapMethodsEntry entry = entries[i];
+ String[] argumentsName = bootstrapArgumentsDescription(entry, constantPool);
+
buffer.append(
Messages.bind(
Messages.disassembler_bootstrapmethodentry,
new String[] {
Integer.toString(i),
Integer.toString(entry.getBootstrapMethodReference()),
- getArguments(entry.getBootstrapArguments())
+ bootstrapMethodDescription(entry, constantPool),
+ getArguments(entry.getBootstrapArguments(), argumentsName)
}));
}
}
- private String getArguments(int[] arguments) {
+ private String getArguments(int[] arguments, String[] argumentsName) {
StringBuffer buffer = new StringBuffer();
- buffer.append('{');
for (int i = 0, max = arguments.length; i < max; i++) {
- if (i != 0) {
- buffer.append(Messages.disassembler_comma);
- }
buffer.append(
Messages.bind(
Messages.disassembler_bootstrapmethodentry_argument,
new String[] {
Integer.toString(arguments[i]),
+ argumentsName[i]
}));
+ if (i != arguments.length - 1)
+ buffer.append("\n\t\t"); //$NON-NLS-1$
}
- buffer.append('}');
return String.valueOf(buffer);
}
private void disassemble(int index, IParameterAnnotation parameterAnnotation, StringBuffer buffer, String lineSeparator, int tabNumber, int mode) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
index 6bb6c17..0cfc4b9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java
@@ -36,6 +36,7 @@
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.core.*;
import org.eclipse.jdt.internal.core.search.AbstractJavaSearchScope;
@@ -209,8 +210,10 @@
if (scope.isLambdaScope()) {
parentElement = createElement(scope.parent, elementPosition, unit, existingElements, knownScopes);
LambdaExpression expression = (LambdaExpression) scope.originalReferenceContext();
- if (expression.resolvedType != null && expression.resolvedType.isValidBinding()) { // chain in lambda element only if resolved properly.
- newElement = new org.eclipse.jdt.internal.core.LambdaExpression((JavaElement) parentElement, expression).getMethod();
+ if (expression.resolvedType != null && expression.resolvedType.isValidBinding() &&
+ !(expression.descriptor instanceof ProblemMethodBinding)) { // chain in lambda element only if resolved properly.
+ //newElement = new org.eclipse.jdt.internal.core.SourceLambdaExpression((JavaElement) parentElement, expression).getMethod();
+ newElement = LambdaFactory.createLambdaExpression((JavaElement) parentElement, expression).getMethod();
knownScopes.put(scope, newElement);
return newElement;
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java
index 529c65f..06f26fb 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/MementoTokenizer.java
@@ -57,6 +57,24 @@
case JavaElement.JEM_COUNT:
return COUNT;
case JavaElement.JEM_JAVAPROJECT:
+ // Also covers JavaElement#JEM_DELIMITER_ESCAPE, in which case,
+ // we seek ahead by one char and check if it's an escaped delimiter
+ // and if that's true, we return that as the token.
+ // Else, we decide that JEM_JAVAPROJECT is the current token.
+ if (this.index < this.length) {
+ char nextChar = this.memento[this.index++];
+ switch(nextChar) {
+ case JavaElement.JEM_LAMBDA_EXPRESSION:
+ return LAMBDA_EXPRESSION;
+ case JavaElement.JEM_LAMBDA_METHOD:
+ return LAMBDA_METHOD;
+ case JavaElement.JEM_STRING:
+ return STRING;
+ default:
+ this.index--;
+ break;
+ }
+ }
return JAVAPROJECT;
case JavaElement.JEM_PACKAGEFRAGMENTROOT:
return PACKAGEFRAGMENTROOT;
@@ -78,12 +96,6 @@
return PACKAGEDECLARATION;
case JavaElement.JEM_IMPORTDECLARATION:
return IMPORTDECLARATION;
- case JavaElement.JEM_LAMBDA_EXPRESSION:
- return LAMBDA_EXPRESSION;
- case JavaElement.JEM_LAMBDA_METHOD:
- return LAMBDA_METHOD;
- case JavaElement.JEM_STRING:
- return STRING;
case JavaElement.JEM_LOCALVARIABLE:
return LOCALVARIABLE;
case JavaElement.JEM_TYPE_PARAMETER:
@@ -111,9 +123,6 @@
case JavaElement.JEM_PACKAGEDECLARATION:
case JavaElement.JEM_IMPORTDECLARATION:
case JavaElement.JEM_LOCALVARIABLE:
- case JavaElement.JEM_LAMBDA_EXPRESSION:
- case JavaElement.JEM_LAMBDA_METHOD:
- case JavaElement.JEM_STRING:
case JavaElement.JEM_TYPE_PARAMETER:
case JavaElement.JEM_ANNOTATION:
break loop;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
index 383ff0f..d5908f8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/messages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2000, 2013 IBM Corporation and others.
+# Copyright (c) 2000, 2014 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
@@ -292,8 +292,8 @@
disassembler_stackmapattributeheader = Stack map : number of frames {0}
disassembler_signatureattributeheader = // Signature: {0}
disassembler_bootstrapmethodattributesheader = Bootstrap methods:
-disassembler_bootstrapmethodentry = {0} : # {1} arguments: {2}
-disassembler_bootstrapmethodentry_argument = #{0}
+disassembler_bootstrapmethodentry = {0} : # {1} {2}\n\tMethod arguments:\n\t\t{3}
+disassembler_bootstrapmethodentry_argument = #{0} {1}
disassembler_indentation = \
disassembler_constantpoolindex =\ #
disassembler_space = \
diff --git a/org.eclipse.jdt.core/pom.xml b/org.eclipse.jdt.core/pom.xml
index 32f03c3..1890dc6 100644
--- a/org.eclipse.jdt.core/pom.xml
+++ b/org.eclipse.jdt.core/pom.xml
@@ -29,6 +29,7 @@
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
+ <version>1.7</version>
<executions>
<execution>
<phase>prepare-package</phase>
diff --git a/org.eclipse.jdt.core/scripts/binary/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/scripts/binary/META-INF/MANIFEST.MF
index 080d0ba..532d8da 100644
--- a/org.eclipse.jdt.core/scripts/binary/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core/scripts/binary/META-INF/MANIFEST.MF
@@ -3,7 +3,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: Eclipse Compiler for Java(TM)
Bundle-SymbolicName: org.eclipse.jdt.core.compiler.batch
-Bundle-Version: 3.9.2.qualifier
+Bundle-Version: 3.10.0.qualifier
Bundle-ClassPath: .
Bundle-Vendor: Eclipse.org
Export-Package: org.eclipse.jdt.core,
diff --git a/org.eclipse.jdt.core/scripts/build.xml b/org.eclipse.jdt.core/scripts/build.xml
index e772a07..8013a32 100644
--- a/org.eclipse.jdt.core/scripts/build.xml
+++ b/org.eclipse.jdt.core/scripts/build.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2007, 2012 IBM Corporation and others.
+ Copyright (c) 2007, 2014 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
@@ -21,21 +21,9 @@
<mkdir dir="${output}" />
<javac srcdir="${basedir}" destdir="${output}"
- debuglevel="lines,source"
- source="1.3"
- target="1.2"
- excludes="org/eclipse/jdt/internal/compiler/tool/*,**/apt/**">
- <compilerarg line="-Xlint:none"/>
- </javac>
-
- <javac destdir="${output}"
- debuglevel="lines,source"
- source="1.6"
- target="1.6"
- includes="org/eclipse/jdt/internal/compiler/tool/*">
- <src path="${basedir}"/>
- <include name="org/eclipse/jdt/internal/compiler/tool/*"/>
- <include name="**/apt/**"/>
+ debuglevel="lines,source"
+ source="1.6"
+ target="1.6">
<compilerarg line="-Xlint:none"/>
</javac>
diff --git a/org.eclipse.jdt.core/scripts/ecj.1 b/org.eclipse.jdt.core/scripts/ecj.1
new file mode 100644
index 0000000..7f91ad0
--- /dev/null
+++ b/org.eclipse.jdt.core/scripts/ecj.1
@@ -0,0 +1,477 @@
+.TH ecj 1 "18 March 2014"
+.LP
+.SH NAME
+ecj \- the eclipse JDT Batch Compiler
+.SH SYNOPSIS
+.B ecj <options> infile
+.B ...
+.SH DESCRIPTION
+.B ecj is the batch compiler from Eclipse and is available as ecj.jar.
+Since 3.3, this jar also contains the support for jsr199 (Compiler API)
+and the support for jsr269 (Annotation processing). In order to use the
+annotations processing support, a 1.6 VM is required.
+
+.SH OPTIONS
+Option Summary
+.sp
+Here is a summary of all the options, grouped by type. Explanations are in the following sections.
+.sp
+.ul 1
+ClassPath Options
+.sp
+\fB\-bootclasspath \-cp|\-classpath \-extdirs \-endorseddirs \-sourcepath \-d \-encoding\fR
+.sp
+.ul 1
+Compliance Options
+.sp
+.B \-target \-1.3 \-1.4 \-1.5 \-1.6 \-1.7 \-1.8 \-source
+.sp
+.ul 1
+Warning Options
+.sp
+.B \-?:warn \-help:warn \-warn:... \-nowarn \-err:... \-deprecation \-properties
+.sp
+.ul
+Debug Options
+.sp
+\fB\-g \-preserveAllLocals \-Akey[=\fIvalue\fB] \-proc:[only|none] \-processor \-processorpath \-s \-XprintProcessorInfo \-XprintRounds \-classNames\fR
+.sp
+.ul
+Ignored Options (for compatibility with javac options)
+.sp
+\-J \-X \-O
+.sp
+.ul
+Advanced Options
+.sp
+\fB@<file> \-maxProblems \-log \-Xemacs \-proceedOnError \-verbose \-referenceInfo \-progress \-time \-noExit \-repeat \-inlineJSR \-enableJavaDoc \-missingNullDefault
+.sp
+.ul
+Helping Options
+.sp
+\-? \-help \-v \-version \-showversion
+.B
+.IP \-bootclasspath <dir 1>;<dir 2>;...;<dir P>
+This is a list of directories or jar files used to bootstrap the class files used by the compiler. By default the libraries of the running VM are used. Entries are separated by the platform path separator.
+Each directory or file can specify access rules for types between '[' and ']'.
+If no bootclasspath is specified, the compiler will infer it using the following system properties sun.boot.class.path, vm.boot.class.path or org.apache.harmony.boot.class.path in this order respectively
+
+.IP "\-cp|\-classpath <dir 1>;dir2;...<dir P>"
+This is a list of directories or jar files used to compile the source files. The default value is the value of the property "java.class.path". Entries are separated by the platform path separator.
+Each directory or file can specify access rules for types between '[' and ']' (e.g. [\-X] to forbid access to type X, [~X] to discourage access to type X, [+p/X:\-p/*] to forbid access to all types in package p but allow access to p/X).
+The compiler follows the Class-Path clauses of jar files' manifests recursively and appends each referenced jar file to the end of the classpath, provided it is not on the classpath yet.
+
+.IP "\-extdirs <dir 1>;<dir 2>;...;<dir P>"
+This is a list of directories used to specify the location of extension zip/jar files. Entries are separated by the platform path separator.
+
+.IP "\-endorseddirs <dir 1>;<dir 2>;...;<dir P>"
+This is a list of directories used to specify the location of endorsed zip/jar files. Entries are separated by the platform path separator.
+
+.IP "\-sourcepath <dir 1>;<dir 2>;...;<dir P>"
+This is a list of directories used to specify the source files. Entries are separated by the platform path separator. Each directory can specify access rules for types between '[' and ']'.
+
+.IP "\-d <dir 1>|none"
+This is used to specify in which directory the generated .class files should be dumped. If it is omitted, no package directory structure is created.
+If you want to generate no .class file at all, use \-d none.
+
+.IP "\-encoding <encoding name>"
+Specify default encoding for all source files. Custom encoding can also be specified on a per file basis by suffixing each input source file/folder name with [<encoding name>]. For example X.java[utf8] would specify the UTF-8 encoding for the compilation unit X.java located in the current user directory.
+If multiple default source file encodings are specified, the last one will be used.
+
+For example:
+
+�... \-encoding UTF-8 X.java[Cp1252] Y.java[UTF-16] Z.java ....
+All source files will be read using UTF-8 encoding (this includes Z.java). X.java will be read using Cp1252 encoding and Y.java will be read using UTF-16 encoding.
+�... \-encoding UTF-8 -encoding UTF-16 ....
+All source files will be read using UTF-16 encoding. The \-encoding option for UTF-8 is ignored.
+�... \-encoding Cp1252 /foo/bar/X.java[UTF-16] /foo/bar[UTF-8] ....
+All source files will be read using Cp1252 encoding. X.java is the only file inside the /foo/bar directory to be read using the encoding UTF-16. All other files in that directory will use UTF-8 encoding.
+
+.IP "\-target 1.1 to 1.8 or (5, 5.0, etc)"
+This specifies the .class file target setting. The possible value are:
+�1.1 (major version: 45 minor: 3)
+�1.2 (major version: 46 minor: 0)
+�1.3 (major version: 47 minor: 0)
+�1.4 (major version: 48 minor: 0)
+�1.5, 5 or 5.0 (major version: 49 minor: 0)
+�1.6, 6 or 6.0 (major version: 50 minor: 0)
+�1.7, 7 or 7.0 (major version: 51 minor: 0)
+�1.8, 8 or 8.0 (major version: 132 minor: 0)
+Defaults are:
+�1.1 in \-1.3 mode
+�1.2 in \-1.4 mode
+�1.5 in \-1.5 mode
+�1.6 in \-1.6 mode
+�1.7 in \-1.7 mode
+�1.8 in \-1.8 mode
+clcd1.1 can be used to generate the StackMap attribute.
+
+.IP \-1.3
+Set compliance level to 1.3. Implicit \-source 1.3 \-target 1.1.
+
+.IP \-1.4
+Set compliance level to 1.4 (default). Implicit \-source 1.3 \-target 1.2.
+
+.IP \-1.5
+Set compliance level to 1.5. Implicit \-source 1.5 \-target 1.5.
+
+.IP \-1.6
+Set compliance level to 1.6. Implicit \-source 1.6 \-target 1.6.
+
+.IP \-1.7
+Set compliance level to 1.7. Implicit \-source 1.7 \-target 1.7.
+
+.IP \-1.8
+Set compliance level to 1.8. Implicit \-source 1.8 \-target 1.8.
+
+.IP "\-source 1.1 to 1.8 or (5, 5.0, etc)"
+This is used to specify the source level expected by the compiler.
+The possible value are:
+�1.3
+�1.4
+�1.5, 5 or 5.0
+�1.6, 6 or 6.0
+�1.7, 7 or 7.0
+�1.8, 8 or 8.0
+
+Defaults are:
+�1.3 in \-1.3 mode
+�1.3 in \-1.4 mode
+�1.5 in \-1.5 mode
+�1.6 in \-1.6 mode
+�1.7 in \-1.7 mode
+�1.8 in \-1.8 mode
+In 1.4, assert is treated as a keyword. In 1.5 and 1.6, enum and assert are treated as a keywords.
+
+
+.IP "\-?:warn \-help:warn"
+Display advanced warning options
+
+.IP "\-warn:..."
+Specify the set of enabled warnings.
+\-warn:none disable all warnings
+\-warn:<warning tokens separated by ,> enable exactly the listed warnings
+\-warn:+<warning tokens separated by ,> enable additional warnings
+\-warn:\-<warning tokens separated by ,> disable specific warnings
+
+Examples:
+
+�\-warn:unusedLocal,deprecation enables only the given two warning options and disables all the other options
+�\-warn:\-unusedLocal,deprecation,+fallthrough disables unusedLocal and deprecation, enables fallthrough, and leaves the other warning options untouched
+In the column Default below, a mark "+/-" indicates that an option covers several fine grained warning variants, some of which are enabled by default, others disabled. This means that specifying the given option with "+" will enable more warnings than the default, and specifying "-" disables some that are enabled by default.
+.sp
+.IP
+.in +.5i
++/- allDeadCode dead code including trivial if (DEBUG) check
+.sp
++/- allDeprecation deprecation even inside deprecated code
+.sp
+- allJavadoc invalid or missing Javadoc
+.sp
+- allOver\-ann all missing @Override annotations (superclass and superinterfaces)
+.sp
+- all-static-method all method can be declared as static warnings
+.sp
++ assertIdentifier occurrence of assert used as identifier
+.sp
+- boxing autoboxing conversion
+.sp
++ charConcat when a char array is used in a string concatenation without being converted explicitly to a string
+.sp
++ compareIdentical comparing identical expressions
+.sp
+- conditionAssign possible accidental boolean assignment
+.sp
++ constructorName method with constructor name
+.sp
++ deadCode dead code excluding trivial if (DEBUG) check
+.sp
+- dep\-ann missing @Deprecated annotation
+.sp
++/- deprecation usage of deprecated type or member outside deprecated code
+.sp
++ discouraged use of types matching a discouraged access rule
+.sp
+- emptyBlock undocumented empty block
+.sp
++ enumIdentifier occurrence of enum used as identifier
+.sp
++ enumSwitch incomplete enum switch
+.sp
+- enumSwitchPedantic report missing enum switch cases even in the presence of a default case
+.sp
+- fallthrough possible fall-through case
+.sp
+- fieldHiding field hiding another variable
+.sp
++ finalBound type parameter with final bound
+.sp
++ finally finally block not completing normally
+.sp
++ forbidden use of types matching a forbidden access rule
+.sp
+- hashCode missing hashCode() method when overriding equals()
+.sp
++/- hiding macro for fieldHiding, localHiding, maskedCatchBlock, and typeHiding
+.sp
+- includeAssertNull raise null warnings for variables that got tainted in an assert expression
+.sp
+- indirectStatic indirect reference to static member
+.sp
+- inheritNullAnnot consider null annotations as being inherited from an overridden method to any overriding methods
+.sp
++ intfAnnotation annotation type used as super interface
+.sp
++ intfNonInherited interface non-inherited method compatibility
+.sp
+- intfRedundant find redundant superinterfaces
+.sp
+- invalidJavadoc macro to toggle the 'malformed Javadoc comments' option and all its sub-options listed below
+.sp
+- invalidJavadocTag report invalid Javadoc tags in Javadoc comments.
+.sp
+- invalidJavadocTagDep report invalid deprecated references in Javadoc tag arguments
+.sp
+- invalidJavadocTagNotVisible report invalid non-visible references in Javadoc tag arguments
+.sp
+- invalidJavadocVisibility(<visibility>) specify visibility modifier ("public", "protected" or "private") for malformed Javadoc tag warnings. Usage example: invalidJavadocVisibility(public)
+.sp
+- javadoc invalid Javadoc
+.sp
+- localHiding local variable hiding another variable
+.sp
++ maskedCatchBlock hidden catch block
+.sp
+- missingJavadocTags macro to toggle the 'missing Javadoc tags' option and all its sub-options listed below
+.sp
+- missingJavadocTagsMethod report missing Javadoc tags for a method's type parameters
+.sp
+- missingJavadocTagsOverriding report missing Javadoc tags in overriding methods
+.sp
+- missingJavadocTagsVisibility(<visibility>) specify visibility modifier ("public", "protected" or "private") for missing Javadoc tags warnings. Usage example: missingJavadocTagsVisibility(public)
+.sp
+- missingJavadocComments macro to toggle the 'missing Javadoc comments' option and all its sub-options listed below
+.sp
+- missingJavadocCommentsOverriding report missing Javadoc comments in overriding methods
+.sp
+- missingJavadocCommentsVisibility(<visibility>) specify visibility modifier ("public", "protected" or "private") for missing Javadoc comments warnings. Usage example: missingJavadocCommentsVisibility(public)
+.sp
+- nls non-nls string literals (lacking of tags //$NON-NLS-<n>)
+.sp
++ noEffectAssign assignment with no effect
+.sp
++ nonnullNotRepeated nonnull parameter annotation from overridden method is not repeated in an overriding method. Is effective only with the nullAnnot option enabled.
+.sp
++/- null potential missing or redundant null check
+.sp
+- nullAnnot enable annotation based null analysis.
+If desired, the annotation types to be interpreted by the compiler can be specified by appending (nullable|nonnull|nonnullbydefault), where each annotation type is specified using its fully qualified name.
+Usage example: nullAnnot(p.Nullable|p.NonNull|p.NonNullByDefault)
+.sp
+Enabling this option enables all null-annotation related sub-options. These can be individually controlled using options listed below
+.sp
+- nullAnnotConflict report conflicts between null annotation specified and nullness inferred. Is effective only with the nullAnnot option enabled.
+.sp
+- nullAnnotRedundant report redundant specification of null annotation. Is effective only with the nullAnnot option enabled.
+.sp
+- nullDereference missing null check
+.sp
+- nullUncheckedConversion report unchecked conversion from unannotated type to @NonNull type. Is effective only with the nullAnnot option enabled.
+.sp
+- over-ann missing @Override annotation (superclass only)
+.sp
+- paramAssign assignment to a parameter
+.sp
++ pkgDefaultMethod attempt to override package-default method
+.sp
++ raw usage a of raw type (instead of a parameterized type)
+.sp
++/- resource (potentially) unsafe usage of resource of type Closeable
+.sp
+- semicolon unnecessary semicolon or empty statement
+.sp
++ serial missing serialVersionUID
+.sp
+- specialParamHiding constructor or setter parameter hiding another field
+.sp
++/- static-access macro for indirectStatic and staticReceiver
+.sp
+- static-method an instance method that could be as a static method
+.sp
++ staticReceiver if a non static receiver is used to get a static field or call a static method
+.sp
+- super overriding a method without making a super invocation
+.sp
++ suppress enable @SuppressWarnings
+.sp
+- switchDefault switch statement lacking a default case
+.sp
+- syncOverride missing synchronized in synchronized method override
+.sp
+- syntheticAccess when performing synthetic access for innerclass
+.sp
+- tasks enable support for tasks tags in source code
+.sp
++ typeHiding type parameter hiding another type
+.sp
++ unavoidableGenericProblems report even unavoidable type safety problems due to raw APIs
+.sp
++ unchecked unchecked type operation
+.sp
+- unnecessaryElse unnecessary else clause
+.sp
+- unqualifiedField unqualified reference to field
+.sp
++/- unused macro for unusedImport, unusedLabel, unusedLocal, unusedPrivate, unusedThrown, unusedTypeArgs, and unusedTypeParameter
+.sp
+- unusedAllocation allocating an object that is not used
+.sp
+- unusedArgument unused method parameter (deprecated option; use unusedParam instead)
+.sp
++ unusedImport unused import reference
+.sp
++ unusedLabel unused label
+.sp
++ unusedLocal unused local variable
+.sp
++ unusedParam unused method parameter
+.sp
++ unusedParamImplementing unused parameter for implementing method
+.sp
++ unusedParamIncludeDoc unused parameter documented in a Javadoc comment tag
+.sp
++ unusedParamOverriding unused parameter for overriding method
+.sp
++ unusedPrivate unused private member declaration
+.sp
+- unusedThrown unused declared thrown exception
+.sp
+- unusedThrownIncludeDocComment unused declared thrown exception documented in a Javadoc comment tag
+.sp
+- unusedThrownExemptExceptionThrowable report unused declared thrown exception but exempt Exception and Throwable
+.sp
+- unusedThrownWhenOverriding unused declared thrown exception in overriding method
+.sp
++ unusedTypeArgs unused type arguments for method and constructor
+.sp
++ unusedTypeParameter unused type parameter
+.sp
+- uselessTypeCheck unnecessary cast/instanceof operation
+.sp
++ varargsCast varargs argument need explicit cast
+.sp
++/- warningToken unhandled or unused warning token in @SuppressWarnings
+.in
+
+.IP \-nowarn
+No warning (equivalent to \-warn:none)
+.IP "\-err:..."
+Specify the set of enabled warnings that are converted to errors.
+e.g. \-err:unusedLocal,deprecation
+unusedLocal and deprecation warnings will be converted to errors. All other warnings are still reported as warnings. \-err:<warning tokens separated by ,> convert exactly the listed warnings to errors
+.IP "\-err:+<warning tokens separated by ,>"
+convert additional warnings to errors
+.IP "\-err:\-<warning tokens separated by ,>"
+remove specific warnings from being converted to errors
+.IP \-deprecation
+Equivalent to \-warn:+deprecation.
+.IP "\-properties <file>"
+Set warnings/errors option based on the properties file contents. This option can be used with \-nowarn, \-err:.. or \-warn:.. options, but the last one on the command line sets the options to be used.
+
+The properties file contents can be generated by setting project specific settings on an existing java project and using the file in .settings/org.eclipse.jdt.core.prefs file as a properties file, or a simple text file that is defined entry/value pairs using the constants defined in the org.eclipse.jdt.core.JavaCore class. Of those constants declared in this class, all options starting with "org.eclipse.jdt.core.compiler." are interpreted by the batch compiler.
+
+...
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+...
+To ensure that a property file has the same effect when used in the IDE and for the batch compiler, use of the \-properties option will change the defaults for a few options:
+
+\-g default changed to all enabled
+\-preserveAllLocals default changed to enabled
+\-enableJavadoc default changed to enabled
+error/warning forbidden default changed to error
+
+.IP "\-g[:none|:lines,vars,source]"
+Set the debug attributes level
+\-g
+All debug info (equivalent to \-g:lines,vars,source)
+ \-g:none
+No debug info
+\-g:[lines,vars,source]
+Selective debug info
+Not specifying this option is equivalent to setting \-g:lines,source.
+.IP "\-preserveAllLocals"
+Explicitly request the compiler to preserve all local variables (for debug purpose). If omitted, the compiler will remove unused locals.
+Annotation processing options (require a 1.6 VM or above and are used only if the compliance is 1.6)
+.IP "\-Akey[=value]"
+Annotation processors options that are passed to annotation processors. key is made of identifiers separated by dots
+
+.IP "\-proc:[only|none] "
+If \-proc:only is specified, the annotation processors will run but no compilation will be performed. If \-proc:none is specified, annotation processors will not be discovered or run; compilation will proceed as if no annotation processors were found. By default the compiler must search the classpath for annotation processors, so specifying \-proc:none may speed compilation if annotation processing is not required.
+.IP "\-processor <class1[,class2,...]> "
+Qualified class names of annotation processors to run. If specified, the normal processor discovery process will be skipped.
+.IP "\-processorpath <dir 1>;<dir 2>;...;<dir P> "
+A list of directories or jar files which will be searched for annotation processors. Entries are separated by the platform path separator. If not specified, the classpath will be searched instead.
+.IP "\-s <dir> "
+The directory where generated source files will be created.
+.IP "\-XprintProcessorInfo "
+Print information about which annotations and which elements a processor is asked to process
+.IP "\-XprintRounds "
+Print information about annotation processing rounds
+.IP "\-classNames <class1[,class2,...]> "
+Qualified names of binary types that need to be processed
+
+.IP "\-J<option>"
+Pass option to the virtual machine
+.IP "\-X<option>"
+Specify non-standard option. \-Xemacs is not ignored.
+.IP "\-X"
+Print non-standard options and exit
+.IP "\-O"
+Optimize for execution time
+
+.IP "@<file>"
+Read command-line arguments from file
+.IP "\-maxProblems <n>"
+Max number of problems per compilation unit (100 by default)
+.IP "\-log <filename>"
+Specify a log file in which all output from the compiler will be dumped. This is really useful if you want to debug the batch compiler or get a file which contains all errors and warnings from a batch build. If the extension is .xml, the generated log will be an xml file.
+.IP "\-Xemacs"
+Use emacs style to present errors and warnings locations into the console and regular text logs. XML logs are unaffected by this option. With this option active, the message:
+2. WARNING in /workspace/X.java
+(at line 8)...
+is presented as:
+/workspace/X.java:8: warning: The method...
+.IP "\-proceedOnError[:Fatal]"
+Keep compiling in spite of errors, dumping class files with problem methods or problem types. This is recommended only if you want to be able to run your application even if you have remaining errors.
+With ":Fatal", all optional errors are treated as fatal and this leads to code that will abort if an error is reached at runtime. Without ":Fatal", optional errors don't prevent the proper code generation and the produced .class files can be run without a problem.
+.IP "\-verbose"
+Print accessed/processed compilation units in the console or the log file if specified.
+.IP "\-referenceInfo"
+Compute reference info. This is useful only if connected to the builder. The reference infos are useless otherwise.
+.IP "\-progress"
+Show progress (only in \-log mode).
+.IP "\-time"
+Display speed information.
+.IP "\-noExit"
+Do not call System.exit(n) at end of compilation (n=0 if no error).
+.IP "\-repeat <n>"
+Repeat compilation process <n> times (perf analysis).
+.IP "\-inlineJSR"
+Inline JSR bytecode (implicit if target >= 1.5).
+.IP "\-enableJavadoc"
+Consider references inside Javadoc. The Javadoc options are effective only when this option is enabled.
+.IP "\-missingNullDefault"
+When annotation based null analysis is enabled (using "nullAnnot", above), this option will raise a warning whenever there is no default annotation on a package or a type.
+.IP "\-? \-help"
+Display the help message.
+.IP "\-v \-version"
+Display the build number of the compiler. This is very useful to report a bug.
+.IP "\-showversion"
+Display the build number of the compiler and continue. This is very useful to report a bug.
+
+.SH BUGS
+To report bugs see https://bugs.eclipse.org/bugs
+.SH AUTHOR
+For details on eclipse committers See http://www.eclipse.org/committers/
diff --git a/org.eclipse.jdt.core/scripts/export-ecj.xml b/org.eclipse.jdt.core/scripts/export-ecj.xml
index 38d45a9..91ea17b 100644
--- a/org.eclipse.jdt.core/scripts/export-ecj.xml
+++ b/org.eclipse.jdt.core/scripts/export-ecj.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2007, 2013 IBM Corporation and others.
+ Copyright (c) 2007, 2014 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
@@ -98,6 +98,7 @@
<delete file="${dest}/ecj-${buildLabel}.jar" failonerror="false"/>
<copy todir="${ecj-temp-folder}">
<fileset dir="scripts/binary" />
+ <fileset dir="scripts" includes="ecj.1"/>
</copy>
<replace file="${ecj-temp-folder}/META-INF/MANIFEST.MF" token="qualifier" value="${bundleVersionQualifer}"/>
<zip zipfile="${dest}/ecj-${buildLabel}.jar">
@@ -126,6 +127,7 @@
</zipfileset>
<fileset dir="${ecj-temp-folder}">
<include name="**/messages.properties"/>
+ <include name="ecj.1"/>
</fileset>
<zipfileset dir="compiler" />
<zipfileset dir="antadapter">
@@ -147,6 +149,7 @@
<delete file="${dest}/ecj_all.jar" failonerror="false"/>
<mkdir dir="${ecj-temp-src-folder}/src" />
<copy todir="${ecj-temp-folder}">
+ <fileset dir="scripts" includes="ecj.1"/>
<fileset dir="scripts/binary" />
</copy>
<replace file="${ecj-temp-folder}/META-INF/MANIFEST.MF" token="qualifier" value="${bundleVersionQualifer}"/>
diff --git a/org.eclipse.jdt.core/scripts/source/META-INF/MANIFEST.MF b/org.eclipse.jdt.core/scripts/source/META-INF/MANIFEST.MF
index 104cbfe..2e28c8e 100644
--- a/org.eclipse.jdt.core/scripts/source/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.core/scripts/source/META-INF/MANIFEST.MF
@@ -2,6 +2,6 @@
Bundle-ManifestVersion: 2
Bundle-Name: Source of Eclipse Compiler for Java(TM)
Bundle-SymbolicName: org.eclipse.jdt.core.compiler.batch.source
-Bundle-Version: 3.9.2.qualifier
+Bundle-Version: 3.10.0.qualifier
Bundle-Vendor: Eclipse.org
-Eclipse-SourceBundle: org.eclipse.jdt.core.compiler.batch;version="3.9.2.${buildQualifier}";roots:="."
+Eclipse-SourceBundle: org.eclipse.jdt.core.compiler.batch;version="3.10.0.${buildQualifier}";roots:="."
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java
index 2a731fb..77f77cd 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/IJavaSearchConstants.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -466,6 +466,17 @@
*/
int IMPLICIT_THIS_REFERENCE = 0x8000000;
+ /**
+ * Return only method reference expressions, e.g. <code>A::foo</code>.
+ * <p>
+ * When this flag is set, only {@link MethodReferenceMatch} matches will be
+ * returned.
+ *</p>
+ * @since 3.10
+ * @category limitTo
+ */
+ int METHOD_REFERENCE_EXPRESSION = 0x10000000;
+
/* Syntactic match modes */
/**
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
index bd1f4a7..802b4f8 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchPattern.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -1544,6 +1544,9 @@
* <tr>
* <td>{@link IJavaSearchConstants#IMPLICIT_THIS_REFERENCE IMPLICIT_THIS_REFERENCE}
* <td>Return only field accesses or method invocations without any qualification.
+ * <tr>
+ * <td>{@link IJavaSearchConstants#METHOD_REFERENCE_EXPRESSION METHOD_REFERENCE_EXPRESSION}
+ * <td>Return only method reference expressions (e.g. <code>A :: foo</code>).
* </table>
* </li>
* </ul>
@@ -1721,7 +1724,10 @@
* <tr>
* <td>{@link IJavaSearchConstants#IMPLICIT_THIS_REFERENCE IMPLICIT_THIS_REFERENCE}
* <td>Return only field accesses or method invocations without any qualification.
- * </table>
+* <tr>
+ * <td>{@link IJavaSearchConstants#METHOD_REFERENCE_EXPRESSION METHOD_REFERENCE_EXPRESSION}
+ * <td>Return only method reference expressions (e.g. <code>A :: foo</code>).
+* </table>
* </li>
* </ul>
* @return a search pattern for a Java element or <code>null</code> if the given element is ill-formed
@@ -1830,6 +1836,9 @@
* <tr>
* <td>{@link IJavaSearchConstants#IMPLICIT_THIS_REFERENCE IMPLICIT_THIS_REFERENCE}
* <td>Return only field accesses or method invocations without any qualification.
+ * <tr>
+ * <td>{@link IJavaSearchConstants#METHOD_REFERENCE_EXPRESSION METHOD_REFERENCE_EXPRESSION}
+ * <td>Return only method reference expressions (e.g. <code>A :: foo</code>).
* </table>
* </li>
* </ul>
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
index e60ac37..a234f40 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorLocator.java
@@ -32,6 +32,9 @@
this.pattern = pattern;
}
+protected int fineGrain() {
+ return this.pattern.fineGrain;
+}
public int match(ASTNode node, MatchingNodeSet nodeSet) { // interested in ExplicitConstructorCall
if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH;
if (!(node instanceof ExplicitConstructorCall)) return IMPOSSIBLE_MATCH;
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java
index 2cdb4a3..a15d400 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/ConstructorPattern.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -52,7 +52,8 @@
IJavaSearchConstants.SUPER_REFERENCE |
IJavaSearchConstants.QUALIFIED_REFERENCE |
IJavaSearchConstants.THIS_REFERENCE |
- IJavaSearchConstants.IMPLICIT_THIS_REFERENCE;
+ IJavaSearchConstants.IMPLICIT_THIS_REFERENCE |
+ IJavaSearchConstants.METHOD_REFERENCE_EXPRESSION;
/**
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java
index f53e2e2..41001c7 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchPattern.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2009 IBM Corporation and others.
+ * Copyright (c) 2004, 2014 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
@@ -157,6 +157,9 @@
case IJavaSearchConstants.IMPLICIT_THIS_REFERENCE:
buffer.append("IMPLICIT_THIS_REFERENCE"); //$NON-NLS-1$
break;
+ case IJavaSearchConstants.METHOD_REFERENCE_EXPRESSION:
+ buffer.append("METHOD_REFERENCE_EXPRESSION"); //$NON-NLS-1$
+ break;
}
}
return buffer.toString();
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
index 6e94fc6..9c80563 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java
@@ -64,6 +64,7 @@
import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.JavaProject;
+import org.eclipse.jdt.internal.core.LambdaFactory;
import org.eclipse.jdt.internal.core.LocalVariable;
import org.eclipse.jdt.internal.core.NameLookup;
import org.eclipse.jdt.internal.core.Openable;
@@ -450,7 +451,7 @@
* Creates an IMethod from the given lambda declaration and type.
*/
protected IJavaElement createHandle(LambdaExpression lambdaExpression, IJavaElement parent) {
- org.eclipse.jdt.internal.core.LambdaExpression lambdaElement = new org.eclipse.jdt.internal.core.LambdaExpression((JavaElement) parent, lambdaExpression);
+ org.eclipse.jdt.internal.core.LambdaExpression lambdaElement = LambdaFactory.createLambdaExpression((JavaElement) parent, lambdaExpression);
IMethod lambdaMethodElement = lambdaElement.getMethod();
this.methodHandles.add(lambdaMethodElement);
return lambdaMethodElement;
@@ -1453,7 +1454,7 @@
}
if (pkgs != null) {
for (int i = 0, length = pkgs.length; i < length; i++) {
- IType type = this.nameLookup.findType(typeName, pkgs[i], false, acceptFlag, true/*consider secondary types*/);
+ IType type = this.nameLookup.findType(typeName, pkgs[i], false, acceptFlag, false, true/*consider secondary types*/);
if (type != null) return type;
}
}
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 7dbd0b4..76339da 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
@@ -524,6 +524,8 @@
super.consumeReferenceExpression(referenceExpression);
if (this.patternFineGrain == 0) {
this.patternLocator.match(referenceExpression, this.nodeSet);
+ } else if ((this.patternFineGrain & IJavaSearchConstants.METHOD_REFERENCE_EXPRESSION) != 0) {
+ this.patternLocator.match(referenceExpression, this.nodeSet);
} else if (referenceExpression.lhs.isThis()) {
if ((this.patternFineGrain & IJavaSearchConstants.THIS_REFERENCE) != 0) {
this.patternLocator.match(referenceExpression, this.nodeSet);
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
index 7978c38..61bc89c 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodLocator.java
@@ -446,7 +446,12 @@
reference = ((SingleMemberAnnotation)reference).memberValuePairs()[0];
this.match.setImplicit(true);
}
- int offset = reference.sourceStart;
+ int offset;
+ if (reference instanceof ReferenceExpression) {
+ offset = ((ReferenceExpression) reference).nameSourceStart;
+ } else {
+ offset = reference.sourceStart;
+ }
int length = reference.sourceEnd - offset + 1;
this.match.setOffset(offset);
this.match.setLength(length);
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java
index e746a32..ea4899a 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MethodPattern.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2014 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
@@ -56,7 +56,8 @@
IJavaSearchConstants.SUPER_REFERENCE |
IJavaSearchConstants.QUALIFIED_REFERENCE |
IJavaSearchConstants.THIS_REFERENCE |
- IJavaSearchConstants.IMPLICIT_THIS_REFERENCE;
+ IJavaSearchConstants.IMPLICIT_THIS_REFERENCE |
+ IJavaSearchConstants.METHOD_REFERENCE_EXPRESSION;
/**
* Method entries are encoded as selector '/' Arity: