Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Herrmann2015-04-28 15:54:14 +0000
committerStephan Herrmann2015-04-28 15:54:14 +0000
commit075533e70f43b34233c7fdad30af6ff9bb0a36a8 (patch)
treeebd195d622208318dc02f82b3005d660728dc1ac /org.eclipse.jdt.core/compiler
parent1e97f79ee10aa0e956f4ba6f5e68262525ef39b0 (diff)
downloadorg.eclipse.objectteams-075533e70f43b34233c7fdad30af6ff9bb0a36a8.tar.gz
org.eclipse.objectteams-075533e70f43b34233c7fdad30af6ff9bb0a36a8.tar.xz
org.eclipse.objectteams-075533e70f43b34233c7fdad30af6ff9bb0a36a8.zip
Update jdt.core to I20150428-0800 (M7 warm-up).
Manually merge from origin (bogus lineend changes): - NullTypeAnnotationTest - AstConverter18Test (no real change) - FormatterBugsTests (no real change) - SpacePreparator - SourceTypeBinding
Diffstat (limited to 'org.eclipse.jdt.core/compiler')
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java13
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/Compiler.java59
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/AllocationExpression.java20
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java80
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java7
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java12
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java181
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Initializer.java21
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java17
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java99
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReturnStatement.java16
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java10
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java5
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java72
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Binding.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BlockScope.java27
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/CaptureBinding.java23
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java9
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java2
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java50
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java29
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java34
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java12
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java9
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java42
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java33
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java11
37 files changed, 663 insertions, 283 deletions
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java
index bef278010..bbfc6c95a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/CompilationResult.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -78,7 +78,7 @@ public class CompilationResult {
public int problemCount;
public int taskCount;
public ICompilationUnit compilationUnit;
- private Map problemsMap;
+ private Map<CategorizedProblem, ReferenceContext> problemsMap;
private Set firstErrors;
private int maxProblemPerUnit;
public char[][][] qualifiedReferences;
@@ -205,7 +205,7 @@ private int computePriority(CategorizedProblem problem){
if (problem.isError()){
priority += P_ERROR;
}
- ReferenceContext context = this.problemsMap == null ? null : (ReferenceContext) this.problemsMap.get(problem);
+ ReferenceContext context = this.problemsMap == null ? null : this.problemsMap.get(problem);
if (context != null){
if (context instanceof AbstractMethodDeclaration){
AbstractMethodDeclaration method = (AbstractMethodDeclaration) context;
@@ -500,6 +500,13 @@ public void record(CategorizedProblem newProblem, ReferenceContext referenceCont
}
}
+ReferenceContext getContext(CategorizedProblem problem) {
+ if (problem != null) {
+ return this.problemsMap.get(problem);
+ }
+ return null;
+}
+
/**
* For now, remember the compiled type using its compound name.
*/
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 963b53ac6..beef5ebec 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
@@ -17,6 +17,7 @@
package org.eclipse.jdt.internal.compiler;
import java.io.PrintWriter;
+import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
@@ -32,6 +33,7 @@ import org.eclipse.jdt.internal.compiler.env.ISourceType;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.CompilerStats;
import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
+import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
@@ -88,6 +90,8 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
//public CompilationUnitResult currentCompilationUnitResult;
public CompilationUnitDeclaration[] unitsToProcess;
public int totalUnits; // (totalUnits-1) gives the last unit in unitToProcess
+
+ private Map<String, APTProblem[]> aptProblems;
// name lookup
public LookupEnvironment lookupEnvironment;
@@ -496,6 +500,7 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
return;
}
} catch (SourceTypeCollisionException e) {
+ backupAptProblems();
reset();
// a generated type was referenced before it was created
// the compiler either created a MissingType or found a BinaryType for it
@@ -511,6 +516,8 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
return;
}
}
+ // Restore the problems before the results are processed and cleaned up.
+ restoreAptProblems();
processCompiledUnits(0);
} catch (AbortCompilation e) {
this.handleInternalException(e, null);
@@ -526,6 +533,58 @@ public class Compiler implements ITypeRequestor, ProblemSeverities {
}
}
+ class APTProblem {
+ CategorizedProblem problem;
+ ReferenceContext context;
+ APTProblem(CategorizedProblem problem, ReferenceContext context) {
+ this.problem = problem;
+ this.context = context;
+ }
+ }
+
+ protected void backupAptProblems() {
+ if (this.unitsToProcess == null) return;
+ for (CompilationUnitDeclaration unitDecl : this.unitsToProcess) {
+ if (unitDecl == null) continue;
+ CompilationResult result = unitDecl.compilationResult;
+ if (result != null && result.hasErrors()) {
+ CategorizedProblem[] errors = result.getErrors();
+ for (CategorizedProblem problem : errors) {
+ if (problem.getCategoryID() == CategorizedProblem.CAT_UNSPECIFIED) {
+ if (this.aptProblems == null) {
+ this.aptProblems = new HashMap<>();
+ }
+ APTProblem[] problems = this.aptProblems.get(new String(unitDecl.getFileName()));
+ if (problems == null) {
+ this.aptProblems.put(
+ new String(unitDecl.getFileName()),
+ new APTProblem[] { new APTProblem(problem, result.getContext(problem)) });
+ } else {
+ APTProblem[] temp = new APTProblem[problems.length + 1];
+ System.arraycopy(problems, 0, temp, 0, problems.length);
+ temp[problems.length] = new APTProblem(problem, result.getContext(problem));
+ this.aptProblems.put(new String(unitDecl.getFileName()), temp);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ protected void restoreAptProblems() {
+ if (this.unitsToProcess != null && this.aptProblems!= null) {
+ for (CompilationUnitDeclaration unit : this.unitsToProcess) {
+ APTProblem[] problems = this.aptProblems.get(new String(unit.getFileName()));
+ if (problems != null) {
+ for (APTProblem problem : problems) {
+ unit.compilationResult.record(problem.problem, problem.context);
+ }
+ }
+ }
+ }
+ this.aptProblems = null; // No need for this.
+ }
+
protected void processCompiledUnits(int startingIndex) throws java.lang.Error {
CompilationUnitDeclaration unit = null;
ProcessTaskManager processingTask = null;
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 9692df5a0..f1ef793b7 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -40,6 +40,7 @@
* 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
* Bug 452788 - [1.8][compiler] Type not correctly inferred in lambda expression
+ * Bug 448709 - [1.8][null] ensure we don't infer types that violate null constraints on a type parameter's bound
* 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
@@ -613,9 +614,18 @@ public TypeBinding resolveType(BlockScope scope) {
if (!isDiamond && this.resolvedType.isParameterizedTypeWithActualArguments()) {
checkTypeArgumentRedundancy((ParameterizedTypeBinding) this.resolvedType, scope);
}
- if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) {
- new ImplicitNullAnnotationVerifier(scope.environment(), compilerOptions.inheritNullAnnotations)
- .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope);
+ if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) {
+ if ((this.binding.tagBits & TagBits.IsNullnessKnown) == 0) {
+ new ImplicitNullAnnotationVerifier(scope.environment(), compilerOptions.inheritNullAnnotations)
+ .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope);
+ }
+ if (compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8) {
+ if (this.binding instanceof ParameterizedGenericMethodBinding && this.typeArguments != null) {
+ TypeVariableBinding[] typeVariables = this.binding.original().typeVariables();
+ for (int i = 0; i < this.typeArguments.length; i++)
+ this.typeArguments[i].checkNullConstraints(scope, typeVariables, i);
+ }
+ }
}
//{ObjectTeams: may need to wrap the resolved type
this.resolvedType = RoleTypeCreator.maybeWrapUnqualifiedRoleType(this.resolvedType, scope, this);
@@ -914,7 +924,7 @@ public TypeBinding invocationTargetType() {
}
public boolean statementExpression() {
- return true;
+ return ((this.bits & ASTNode.ParenthesizedMASK) == 0);
}
//-- interface Invocation: --
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 cc8bae713..2a2638004 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
@@ -56,6 +56,7 @@ import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutB
*
* Annotation
*/
+@SuppressWarnings({"rawtypes", "unchecked"})
public abstract class Annotation extends Expression {
Annotation persistibleAnnotation = this; // Emit this into class file, unless this is a repeating annotation, in which case package this into the designated container.
@@ -987,37 +988,13 @@ public abstract class Annotation extends Expression {
return this.resolvedType;
}
- static boolean isAnnotationTargetAllowed(Annotation annotation, BlockScope scope, TypeBinding annotationType, int kind) {
- long metaTagBits = annotationType.getAnnotationTagBits(); // could be forward reference
- if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) {
- // does not specify any target restriction - all locations supported in Java 7 and before are possible
- if (kind == Binding.TYPE_PARAMETER || kind == Binding.TYPE_USE) {
- scope.problemReporter().explitAnnotationTargetRequired(annotation);
- }
- return true;
- }
-
- // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391201
- if ((metaTagBits & TagBits.SE7AnnotationTargetMASK) == 0
- && (metaTagBits & (TagBits.AnnotationForTypeUse | TagBits.AnnotationForTypeParameter)) != 0) {
- if (scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_8) {
- switch (kind) {
- case Binding.PACKAGE :
- case Binding.TYPE :
- case Binding.GENERIC_TYPE :
- case Binding.METHOD :
- case Binding.FIELD :
- case Binding.LOCAL :
- scope.problemReporter().invalidUsageOfTypeAnnotations(annotation);
- }
- }
- }
+ private static boolean isAnnotationTargetAllowed(Binding recipient, BlockScope scope, TypeBinding annotationType, int kind, long metaTagBits) {
switch (kind) {
case Binding.PACKAGE :
if ((metaTagBits & TagBits.AnnotationForPackage) != 0)
return true;
else if (scope.compilerOptions().sourceLevel <= ClassFileConstants.JDK1_6) {
- SourceTypeBinding sourceType = (SourceTypeBinding) annotation.recipient;
+ SourceTypeBinding sourceType = (SourceTypeBinding) recipient;
if (CharOperation.equals(sourceType.sourceName, TypeConstants.PACKAGE_INFO_NAME))
return true;
}
@@ -1034,18 +1011,18 @@ public abstract class Annotation extends Expression {
break;
case Binding.TYPE :
case Binding.GENERIC_TYPE :
- if (((ReferenceBinding)annotation.recipient).isAnnotationType()) {
+ if (((ReferenceBinding)recipient).isAnnotationType()) {
if ((metaTagBits & (TagBits.AnnotationForAnnotationType | TagBits.AnnotationForType | TagBits.AnnotationForTypeUse)) != 0)
return true;
} else if ((metaTagBits & (TagBits.AnnotationForType | TagBits.AnnotationForTypeUse)) != 0) {
return true;
} else if ((metaTagBits & TagBits.AnnotationForPackage) != 0) {
- if (CharOperation.equals(((ReferenceBinding) annotation.recipient).sourceName, TypeConstants.PACKAGE_INFO_NAME))
+ if (CharOperation.equals(((ReferenceBinding) recipient).sourceName, TypeConstants.PACKAGE_INFO_NAME))
return true;
}
//{ObjectTeams: allow @Override for roles:
- if ( (((ReferenceBinding)annotation.recipient).isRole())
- && (annotation.resolvedType.id == TypeIds.T_JavaLangOverride))
+ if ( (((ReferenceBinding)recipient).isRole())
+ && (annotationType.id == TypeIds.T_JavaLangOverride))
return true;
//SH}
break;
@@ -1057,7 +1034,7 @@ public abstract class Annotation extends Expression {
break;
//SH}
case Binding.METHOD :
- MethodBinding methodBinding = (MethodBinding) annotation.recipient;
+ MethodBinding methodBinding = (MethodBinding) recipient;
if (methodBinding.isConstructor()) {
if ((metaTagBits & (TagBits.AnnotationForConstructor | TagBits.AnnotationForTypeUse)) != 0)
return true;
@@ -1075,7 +1052,7 @@ public abstract class Annotation extends Expression {
if ((metaTagBits & TagBits.AnnotationForField) != 0) {
return true;
} else if ((metaTagBits & TagBits.AnnotationForTypeUse) != 0) {
- FieldBinding sourceField = (FieldBinding) annotation.recipient;
+ FieldBinding sourceField = (FieldBinding) recipient;
SourceTypeBinding sourceType = (SourceTypeBinding) sourceField.declaringClass;
FieldDeclaration fieldDeclaration = sourceType.scope.referenceContext.declarationOf(sourceField);
if (isTypeUseCompatible(fieldDeclaration.type, scope)) {
@@ -1084,7 +1061,7 @@ public abstract class Annotation extends Expression {
}
break;
case Binding.LOCAL :
- LocalVariableBinding localVariableBinding = (LocalVariableBinding) annotation.recipient;
+ LocalVariableBinding localVariableBinding = (LocalVariableBinding) recipient;
if ((localVariableBinding.tagBits & TagBits.IsArgument) != 0) {
if ((metaTagBits & TagBits.AnnotationForParameter) != 0) {
return true;
@@ -1110,6 +1087,43 @@ public abstract class Annotation extends Expression {
return false;
}
+ public static boolean isAnnotationTargetAllowed(BlockScope scope, TypeBinding annotationType, Binding recipient) {
+ long metaTagBits = annotationType.getAnnotationTagBits(); // could be forward reference
+ if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) {
+ return true;
+ }
+ return isAnnotationTargetAllowed(recipient, scope, annotationType, recipient.kind(), metaTagBits);
+ }
+
+ static boolean isAnnotationTargetAllowed(Annotation annotation, BlockScope scope, TypeBinding annotationType, int kind) {
+
+ long metaTagBits = annotationType.getAnnotationTagBits(); // could be forward reference
+ if ((metaTagBits & TagBits.AnnotationTargetMASK) == 0) {
+ // does not specify any target restriction - all locations supported in Java 7 and before are possible
+ if (kind == Binding.TYPE_PARAMETER || kind == Binding.TYPE_USE) {
+ scope.problemReporter().explitAnnotationTargetRequired(annotation);
+ }
+ return true;
+ }
+
+ // https://bugs.eclipse.org/bugs/show_bug.cgi?id=391201
+ if ((metaTagBits & TagBits.SE7AnnotationTargetMASK) == 0
+ && (metaTagBits & (TagBits.AnnotationForTypeUse | TagBits.AnnotationForTypeParameter)) != 0) {
+ if (scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_8) {
+ switch (kind) {
+ case Binding.PACKAGE :
+ case Binding.TYPE :
+ case Binding.GENERIC_TYPE :
+ case Binding.METHOD :
+ case Binding.FIELD :
+ case Binding.LOCAL :
+ scope.problemReporter().invalidUsageOfTypeAnnotations(annotation);
+ }
+ }
+ }
+ return isAnnotationTargetAllowed(annotation.recipient, scope, annotationType, kind, metaTagBits);
+ }
+
static void checkAnnotationTarget(Annotation annotation, BlockScope scope, ReferenceBinding annotationType, int kind, Binding recipient, long tagBitsToRevert) {
// check (meta)target compatibility
if (!annotationType.isValidBinding()) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
index c6e5fead0..b842bd35e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Assignment.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -30,6 +30,7 @@
* 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 453483 - [compiler][null][loop] Improve null analysis for loops
+ * Bug 407414 - [compiler][null] Incorrect warning on a primitive type being null
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -194,6 +195,8 @@ FieldBinding getLastField(Expression someExpression) {
}
public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
+ if ((this.implicitConversion & TypeIds.BOXING) != 0)
+ return FlowInfo.NON_NULL;
return this.expression.nullStatus(flowInfo, flowContext);
}
@@ -336,6 +339,6 @@ public LocalVariableBinding localVariableBinding() {
return this.lhs.localVariableBinding();
}
public boolean statementExpression() {
- return true;
+ return ((this.bits & ASTNode.ParenthesizedMASK) == 0);
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
index c42e78067..4e740a628 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Block.java
@@ -15,6 +15,7 @@
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
* bug 383368 - [compiler][null] syntactic null analysis for field references
* bug 402993 - [null] Follow up of bug 401088: Missing warning about redundant null check
+ * Bug 440282 - [resource] Resource leak detection false negative with empty finally block
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -60,9 +61,11 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
flowContext.expireNullCheckedFieldInfo();
}
}
- if (this.explicitDeclarations > 0) {
- // if block has its own scope analyze tracking vars now:
+ if (this.scope != currentScope) {
+ // if block is tracking any resources other than the enclosing 'currentScope', analyse them now:
this.scope.checkUnclosedCloseables(flowInfo, flowContext, null, null);
+ }
+ if (this.explicitDeclarations > 0) {
// cleanup assignment info for locals that are scoped to this block:
LocalVariableBinding[] locals = this.scope.locals;
if (locals != null) {
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 bd9b012c1..97a4a1d3a 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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,7 @@
* 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
* Bug 435805 - [1.8][compiler][null] Java 8 compiler does not recognize declaration style null annotations
+ * Bug 407414 - [compiler][null] Incorrect warning on a primitive type being null
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 415541 - [1.8][compiler] Type annotations in the body of static initializer get dropped
*******************************************************************************/
@@ -591,6 +592,8 @@ public LocalVariableBinding localVariableBinding() {
}
public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
+ if ((this.implicitConversion & TypeIds.BOXING) != 0)
+ return FlowInfo.NON_NULL;
return this.expression.nullStatus(flowInfo, flowContext);
}
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 079a10870..d285c6d72 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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,7 @@
* Bug 427438 - [1.8][compiler] NPE at org.eclipse.jdt.internal.compiler.ast.ConditionalExpression.generateCode(ConditionalExpression.java:280)
* Bug 418537 - [1.8][null] Fix null type annotation analysis for poly conditional expressions
* Bug 428352 - [1.8][compiler] Resolution errors don't always surface
+ * Bug 407414 - [compiler][null] Incorrect warning on a primitive type being null
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -418,6 +419,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext,
}
public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
+ if ((this.implicitConversion & TypeIds.BOXING) != 0)
+ return FlowInfo.NON_NULL;
return this.nullStatus;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
index 6cf57e7fa..6ef6d1de0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ConstructorDeclaration.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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 435805 - [1.8][compiler][null] Java 8 compiler does not recognize declaration style null annotations
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 415399 - [1.8][compiler] Type annotations on constructor results dropped by the code generator
+ * Ulrich Grave <ulrich.grave@gmx.de> - Contributions for
+ * bug 386692 - Missing "unused" warning on "autowired" fields
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -379,6 +381,14 @@ boolean isValueProvidedUsingAnnotation(FieldDeclaration fieldDecl) {
if (CharOperation.equals(memberValuePairs[j].name, TypeConstants.OPTIONAL))
return memberValuePairs[j].value instanceof FalseLiteral;
}
+ } else if (annotation.resolvedType.id == TypeIds.T_OrgSpringframeworkBeansFactoryAnnotationAutowired) {
+ MemberValuePair[] memberValuePairs = annotation.memberValuePairs();
+ if (memberValuePairs == Annotation.NoValuePairs)
+ return true;
+ for (int j = 0; j < memberValuePairs.length; j++) {
+ if (CharOperation.equals(memberValuePairs[j].name, TypeConstants.REQUIRED))
+ return memberValuePairs[j].value instanceof TrueLiteral;
+ }
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java
index 45b882b53..1a1f7878a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FakedTrackingVariable.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2014 GK Software AG and others.
+ * Copyright (c) 2011, 2015 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
@@ -13,7 +13,9 @@
package org.eclipse.jdt.internal.compiler.ast;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@@ -33,6 +35,7 @@ import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
@@ -182,6 +185,8 @@ public class FakedTrackingVariable extends LocalDeclaration {
return local.closeTracker;
if (!isAnyCloseable(expression.resolvedType))
return null;
+ if ((local.tagBits & TagBits.IsResource) != 0)
+ return null;
// tracking var doesn't yet exist. This happens in finally block
// which is analyzed before the corresponding try block
Statement location = local.declaration;
@@ -237,6 +242,8 @@ public class FakedTrackingVariable extends LocalDeclaration {
ConditionalExpression conditional = (ConditionalExpression) location;
return containsAllocation(conditional.valueIfTrue) || containsAllocation(conditional.valueIfFalse);
}
+ if (location instanceof CastExpression)
+ return containsAllocation(((CastExpression) location).expression);
return false;
}
@@ -246,6 +253,8 @@ public class FakedTrackingVariable extends LocalDeclaration {
preConnectTrackerAcrossAssignment(location, local, flowInfo, (AllocationExpression) expression, closeTracker);
} else if (expression instanceof ConditionalExpression) {
preConnectTrackerAcrossAssignment(location, local, flowInfo, (ConditionalExpression) expression, closeTracker);
+ } else if (expression instanceof CastExpression) {
+ preConnectTrackerAcrossAssignment(location, local, ((CastExpression) expression).expression, flowInfo);
}
}
@@ -273,7 +282,7 @@ public class FakedTrackingVariable extends LocalDeclaration {
if (((ReferenceBinding)allocation.resolvedType).hasTypeBit(TypeIds.BitResourceFreeCloseable)) {
// remove unnecessary attempts (closeable is not relevant)
if (allocation.closeTracker != null) {
- scope.removeTrackingVar(allocation.closeTracker);
+ allocation.closeTracker.withdraw();
allocation.closeTracker = null;
}
} else if (((ReferenceBinding)allocation.resolvedType).hasTypeBit(TypeIds.BitWrapperCloseable)) {
@@ -328,7 +337,7 @@ public class FakedTrackingVariable extends LocalDeclaration {
if (isWrapper) {
// remove unnecessary attempts (wrapper has no relevant inner)
if (allocation.closeTracker != null) {
- scope.removeTrackingVar(allocation.closeTracker);
+ allocation.closeTracker.withdraw();
allocation.closeTracker = null;
}
} else {
@@ -353,7 +362,7 @@ public class FakedTrackingVariable extends LocalDeclaration {
}
private static FakedTrackingVariable pick(FakedTrackingVariable tracker1, FakedTrackingVariable tracker2, BlockScope scope) {
- scope.removeTrackingVar(tracker2);
+ tracker2.withdraw();
return tracker1;
}
@@ -600,14 +609,14 @@ public class FakedTrackingVariable extends LocalDeclaration {
if (expression instanceof AllocationExpression) {
FakedTrackingVariable tracker = ((AllocationExpression) expression).closeTracker;
if (tracker != null && tracker.originalBinding == null) {
- currentScope.removeTrackingVar(tracker);
+ tracker.withdraw();
((AllocationExpression) expression).closeTracker = null;
}
} else {
// assignment passing a local into a field?
LocalVariableBinding local = expression.localVariableBinding();
if (local != null && local.closeTracker != null && ((lhsBits & Binding.FIELD) != 0))
- currentScope.removeTrackingVar(local.closeTracker); // TODO: may want to use local.closeTracker.markPassedToOutside(..,true)
+ local.closeTracker.withdraw(); // TODO: may want to use local.closeTracker.markPassedToOutside(..,true)
}
}
@@ -686,7 +695,7 @@ public class FakedTrackingVariable extends LocalDeclaration {
int finallyStatus = currentScope.finallyInfo.nullStatus(local);
if (finallyStatus == FlowInfo.NON_NULL)
return finallyStatus;
- if (finallyStatus != FlowInfo.NULL) // neither is NON_NULL, but not both are NULL => call it POTENTIALLY_NULL
+ if (finallyStatus != FlowInfo.NULL && currentScope.finallyInfo.hasNullInfoFor(local)) // neither is NON_NULL, but not both are NULL => call it POTENTIALLY_NULL
status = FlowInfo.POTENTIALLY_NULL;
}
if (currentScope != outerScope && currentScope.parent instanceof BlockScope)
@@ -701,7 +710,7 @@ public class FakedTrackingVariable extends LocalDeclaration {
do {
flowInfo.markAsDefinitelyNonNull(current.binding);
current.globalClosingState |= CLOSE_SEEN;
- flowContext.markFinallyNullStatus(this.binding, FlowInfo.NON_NULL);
+ flowContext.markFinallyNullStatus(current.binding, FlowInfo.NON_NULL);
current = current.innerTracker;
} while (current != null);
}
@@ -739,44 +748,100 @@ public class FakedTrackingVariable extends LocalDeclaration {
return flowInfo;
}
- /**
- * Pick tracking variables from 'varsOfScope' to establish a proper order of processing:
- * As much as possible pick wrapper resources before their inner resources.
- * Also consider cases of wrappers and their inners being declared at different scopes.
+ /**
+ * Iterator for a set of FakedTrackingVariable, which dispenses the elements
+ * according to the priorities defined by enum {@link Stage}.
+ * Resources whose outer is owned by an enclosing scope are never answered,
+ * unless we are analysing on behalf of an exit (return/throw).
*/
- public static FakedTrackingVariable pickVarForReporting(Set varsOfScope, BlockScope scope, boolean atExit) {
- if (varsOfScope.isEmpty()) return null;
- FakedTrackingVariable trackingVar = (FakedTrackingVariable) varsOfScope.iterator().next();
- while (trackingVar.outerTracker != null) {
- // resource is wrapped, is wrapper defined in this scope?
- if (varsOfScope.contains(trackingVar.outerTracker)) {
- // resource from same scope, travel up the wrapper chain
- trackingVar = trackingVar.outerTracker;
- } else if (atExit) {
- // at an exit point we report against inner despite a wrapper that may/may not be closed later
- break;
- } else {
- BlockScope outerTrackerScope = trackingVar.outerTracker.binding.declaringScope;
- if (outerTrackerScope == scope) {
- // outerTracker is from same scope and already processed -> pick trackingVar now
- break;
- } else {
- // outer resource is from other (outer?) scope
- Scope currentScope = scope;
- while ((currentScope = currentScope.parent) instanceof BlockScope) {
- if (outerTrackerScope == currentScope) {
- // at end of block pass responsibility for inner resource to outer scope holding a wrapper
- varsOfScope.remove(trackingVar); // drop this one
- // pick a next candidate:
- return pickVarForReporting(varsOfScope, scope, atExit);
+ public static class IteratorForReporting implements Iterator<FakedTrackingVariable> {
+
+ private final Set<FakedTrackingVariable> varSet;
+ private final Scope scope;
+ private final boolean atExit;
+
+ private Stage stage;
+ private Iterator<FakedTrackingVariable> iterator;
+ private FakedTrackingVariable next;
+
+ enum Stage {
+ /** 1. prio: all top-level resources, ie., resources with no outer. */
+ OuterLess,
+ /** 2. prio: resources whose outer has already been processed (element of the same varSet). */
+ InnerOfProcessed,
+ /** 3. prio: resources whose outer is not owned by any enclosing scope. */
+ InnerOfNotEnclosing,
+ /** 4. prio: when analysing on behalf of an exit point: anything not picked before. */
+ AtExit
+ }
+
+ public IteratorForReporting(List<FakedTrackingVariable> variables, Scope scope, boolean atExit) {
+ this.varSet = new HashSet<>(variables);
+ this.scope = scope;
+ this.atExit = atExit;
+ setUpForStage(Stage.OuterLess);
+ }
+ @Override
+ public boolean hasNext() {
+ FakedTrackingVariable trackingVar;
+ switch (this.stage) {
+ case OuterLess:
+ while (this.iterator.hasNext()) {
+ trackingVar = this.iterator.next();
+ if (trackingVar.outerTracker == null)
+ return found(trackingVar);
+ }
+ setUpForStage(Stage.InnerOfProcessed);
+ //$FALL-THROUGH$
+ case InnerOfProcessed:
+ while (this.iterator.hasNext()) {
+ trackingVar = this.iterator.next();
+ FakedTrackingVariable outer = trackingVar.outerTracker;
+ if (outer.binding.declaringScope == this.scope && !this.varSet.contains(outer))
+ return found(trackingVar);
+ }
+ setUpForStage(Stage.InnerOfNotEnclosing);
+ //$FALL-THROUGH$
+ case InnerOfNotEnclosing:
+ searchAlien: while (this.iterator.hasNext()) {
+ trackingVar = this.iterator.next();
+ FakedTrackingVariable outer = trackingVar.outerTracker;
+ if (!this.varSet.contains(outer)) {
+ Scope outerTrackerScope = outer.binding.declaringScope;
+ Scope currentScope = this.scope;
+ while ((currentScope = currentScope.parent) instanceof BlockScope) {
+ if (outerTrackerScope == currentScope)
+ break searchAlien;
+ }
+ return found(trackingVar);
}
}
- break; // not parent owned -> pick this var
- }
+ setUpForStage(Stage.AtExit);
+ //$FALL-THROUGH$
+ case AtExit:
+ if (this.atExit && this.iterator.hasNext())
+ return found(this.iterator.next());
+ return false;
+ default: throw new IllegalStateException("Unexpected Stage "+this.stage); //$NON-NLS-1$
}
}
- varsOfScope.remove(trackingVar);
- return trackingVar;
+ private boolean found(FakedTrackingVariable trackingVar) {
+ this.iterator.remove();
+ this.next = trackingVar;
+ return true;
+ }
+ private void setUpForStage(Stage nextStage) {
+ this.iterator = this.varSet.iterator();
+ this.stage = nextStage;
+ }
+ @Override
+ public FakedTrackingVariable next() {
+ return this.next;
+ }
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
}
/**
@@ -824,6 +889,11 @@ public class FakedTrackingVariable extends LocalDeclaration {
return false;
}
+ public void withdraw() {
+ // must unregister at the declaringScope, note that twr resources are owned by the scope enclosing the twr
+ this.binding.declaringScope.removeTrackingVar(this);
+ }
+
public void recordErrorLocation(ASTNode location, int nullStatus) {
if ((this.globalClosingState & OWNED_BY_OUTSIDE) != 0) {
return;
@@ -833,14 +903,20 @@ public class FakedTrackingVariable extends LocalDeclaration {
this.recordedLocations.put(location, new Integer(nullStatus));
}
- public boolean reportRecordedErrors(Scope scope, int mergedStatus) {
+ public boolean reportRecordedErrors(Scope scope, int mergedStatus, boolean atDeadEnd) {
FakedTrackingVariable current = this;
while (current.globalClosingState == 0) {
current = current.innerTracker;
if (current == null) {
// no relevant state found -> report:
- reportError(scope.problemReporter(), null, mergedStatus);
- return true;
+ if (atDeadEnd && neverClosedAtLocations())
+ mergedStatus = FlowInfo.NULL;
+ if ((mergedStatus & (FlowInfo.NULL|FlowInfo.POTENTIALLY_NULL|FlowInfo.POTENTIALLY_NON_NULL)) != 0) {
+ reportError(scope.problemReporter(), null, mergedStatus);
+ return true;
+ } else {
+ break;
+ }
}
}
boolean hasReported = false;
@@ -863,6 +939,15 @@ public class FakedTrackingVariable extends LocalDeclaration {
return hasReported;
}
+ private boolean neverClosedAtLocations() {
+ if (this.recordedLocations != null) {
+ for (Object value : this.recordedLocations.values())
+ if (!value.equals(FlowInfo.NULL))
+ return false;
+ }
+ return true;
+ }
+
public int reportError(ProblemReporter problemReporter, ASTNode location, int nullStatus) {
if ((this.globalClosingState & OWNED_BY_OUTSIDE) != 0) {
return 0; // TODO: should we still propagate some flags??
@@ -903,14 +988,6 @@ public class FakedTrackingVariable extends LocalDeclaration {
}
}
- public void resetReportingBits() {
- FakedTrackingVariable current = this;
- do {
- current.globalClosingState &= ~(REPORTED_POTENTIAL_LEAK|REPORTED_DEFINITIVE_LEAK);
- current = current.innerTracker;
- } while (current != null);
- }
-
public String nameForReporting(ASTNode location, ReferenceContext referenceContext) {
if (this.name == UNASSIGNED_CLOSEABLE_NAME) {
if (location != null && referenceContext != null) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Initializer.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Initializer.java
index 3796302b1..3e72271f8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Initializer.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Initializer.java
@@ -1,15 +1,17 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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:
+ *Contributors:
* IBM Corporation - initial API and implementation
+ * Stephan Herrmann - Contribution for
+ * Bug 429813 - [1.8][dom ast] IMethodBinding#getJavaElement() should return IMethod for lambda
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
+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.codegen.*;
@@ -24,6 +26,8 @@ public class Initializer extends FieldDeclaration {
public int bodyStart;
public int bodyEnd;
+ private MethodBinding methodBinding;
+
public Initializer(Block block, int modifiers) {
this.block = block;
this.modifiers = modifiers;
@@ -126,6 +130,17 @@ public class Initializer extends FieldDeclaration {
}
}
+ /** Method used only by DOM to support bindings of initializers. */
+ public MethodBinding getMethodBinding() {
+ if (this.methodBinding == null) {
+ Scope scope = this.block.scope;
+ this.methodBinding = isStatic()
+ ? new MethodBinding(ClassFileConstants.AccStatic, CharOperation.NO_CHAR, TypeBinding.VOID, Binding.NO_PARAMETERS, Binding.NO_EXCEPTIONS, scope.enclosingSourceType())
+ : new MethodBinding(0, CharOperation.NO_CHAR, TypeBinding.VOID, Binding.NO_PARAMETERS, Binding.NO_EXCEPTIONS, scope.enclosingSourceType());
+ }
+ return this.methodBinding;
+ }
+
public void traverse(ASTVisitor visitor, MethodScope scope) {
if (visitor.visit(this, scope)) {
if (this.block != null) this.block.traverse(visitor, scope);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
index fd8c73f25..1d7dbf489 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MessageSend.java
@@ -52,6 +52,7 @@
* Bug 441734 - [1.8][inference] Generic method with nested parameterized type argument fails on method reference
* Bug 452788 - [1.8][compiler] Type not correctly inferred in lambda expression
* Bug 456487 - [1.8][null] @Nullable type variant of @NonNull-constrained type parameter causes grief
+ * Bug 407414 - [compiler][null] Incorrect warning on a primitive type being null
* 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
@@ -736,6 +737,8 @@ public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo f
// SH}
}
public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
+ if ((this.implicitConversion & TypeIds.BOXING) != 0)
+ return FlowInfo.NON_NULL;
if (this.binding.isValidBinding()) {
// try to retrieve null status of this message send from an annotation of the called method:
long tagBits = this.binding.tagBits;
@@ -1632,7 +1635,7 @@ public void traverse(ASTVisitor visitor, BlockScope blockScope) {
visitor.endVisit(this, blockScope);
}
public boolean statementExpression() {
- return true;
+ return ((this.bits & ASTNode.ParenthesizedMASK) == 0);
}
public boolean receiverIsImplicitThis() {
return this.receiver.isImplicitThis();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
index c090aaaa9..31ebefe7e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/QualifiedAllocationExpression.java
@@ -53,6 +53,7 @@ import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.ImplicitNullAnnotationVerifier;
import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.PolyTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
@@ -64,6 +65,7 @@ import org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.ConstructorDecapsulationException;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.OTQualifiedAllocationExpression;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
@@ -361,9 +363,18 @@ public static abstract class AbstractQualifiedAllocationExpression extends Alloc
TypeBinding result = resolveTypeForQualifiedAllocationExpression(scope);
if (result != null && !result.isPolyType() && this.binding != null) {
final CompilerOptions compilerOptions = scope.compilerOptions();
- if (compilerOptions.isAnnotationBasedNullAnalysisEnabled && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) {
- new ImplicitNullAnnotationVerifier(scope.environment(), compilerOptions.inheritNullAnnotations)
- .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope);
+ if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) {
+ if ((this.binding.tagBits & TagBits.IsNullnessKnown) == 0) {
+ new ImplicitNullAnnotationVerifier(scope.environment(), compilerOptions.inheritNullAnnotations)
+ .checkImplicitNullAnnotations(this.binding, null/*srcMethod*/, false, scope);
+ }
+ if (compilerOptions.sourceLevel >= ClassFileConstants.JDK1_8) {
+ if (this.binding instanceof ParameterizedGenericMethodBinding && this.typeArguments != null) {
+ TypeVariableBinding[] typeVariables = this.binding.original().typeVariables();
+ for (int i = 0; i < this.typeArguments.length; i++)
+ this.typeArguments[i].checkNullConstraints(scope, typeVariables, i);
+ }
+ }
}
}
return result;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
index 96ebe04ae..281de66ff 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Reference.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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 392384 - [1.8][compiler][null] Restore nullness info from type annotations in class files
* Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
* Bug 411964 - [1.8][null] leverage null type annotation in foreach statement
+ * Bug 407414 - [compiler][null] Incorrect warning on a primitive type being null
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
@@ -157,6 +158,8 @@ public FieldBinding lastFieldBinding() {
}
public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
+ if ((this.implicitConversion & TypeIds.BOXING) != 0)
+ return FlowInfo.NON_NULL;
FieldBinding fieldBinding = lastFieldBinding();
if (fieldBinding != null) {
if (fieldBinding.isNonNull() || flowContext.isNullcheckedFieldAccess(this)) {
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 a7adb889c..a4b0a2c6b 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
@@ -34,6 +34,7 @@
* Bug 438945 - [1.8] NullPointerException InferenceContext18.checkExpression in java 8 with generics, primitives, and overloading
* Bug 452788 - [1.8][compiler] Type not correctly inferred in lambda expression
* Bug 448709 - [1.8][null] ensure we don't infer types that violate null constraints on a type parameter's bound
+ * Bug 459967 - [null] compiler should know about nullness of special methods like MyEnum.valueOf()
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contribution for
* Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work)
*******************************************************************************/
@@ -57,6 +58,7 @@ import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
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;
@@ -576,6 +578,7 @@ public class ReferenceExpression extends FunctionalExpression implements IPolyEx
scope.problemReporter().constructedArrayIncompatible(this, lhsType, this.descriptor.returnType);
return this.resolvedType = null;
}
+ checkNullAnnotations(scope);
return this.resolvedType;
}
@@ -697,44 +700,7 @@ public class ReferenceExpression extends FunctionalExpression implements IPolyEx
}
scope.problemReporter().unhandledException(methodExceptions[i], this);
}
- if (scope.compilerOptions().isAnnotationBasedNullAnalysisEnabled) {
- if (this.expectedType == null || !NullAnnotationMatching.hasContradictions(this.expectedType)) { // otherwise assume it has been reported and we can do nothing here
- // TODO: simplify by using this.freeParameters?
- int len;
- int expectedlen = this.binding.parameters.length;
- int providedLen = this.descriptor.parameters.length;
- if (this.receiverPrecedesParameters)
- providedLen--; // one parameter is 'consumed' as the receiver
- boolean isVarArgs = false;
- if (this.binding.isVarargs()) {
- isVarArgs = (providedLen == expectedlen)
- ? !this.descriptor.parameters[expectedlen-1].isCompatibleWith(this.binding.parameters[expectedlen-1])
- : true;
- len = providedLen; // binding parameters will be padded from InferenceContext18.getParameter()
- } else {
- len = Math.min(expectedlen, providedLen);
- }
- for (int i = 0; i < len; i++) {
- TypeBinding descriptorParameter = this.descriptor.parameters[i + (this.receiverPrecedesParameters ? 1 : 0)];
- TypeBinding bindingParameter = InferenceContext18.getParameter(this.binding.parameters, i, isVarArgs);
- NullAnnotationMatching annotationStatus = NullAnnotationMatching.analyse(bindingParameter, descriptorParameter, FlowInfo.UNKNOWN);
- if (annotationStatus.isAnyMismatch()) {
- // immediate reporting:
- scope.problemReporter().referenceExpressionArgumentNullityMismatch(this, bindingParameter, descriptorParameter, this.descriptor, i, annotationStatus);
- }
- }
- if (!this.binding.isConstructor() && (this.descriptor.returnType.tagBits & TagBits.AnnotationNonNull) != 0) {
- // since constructors never return null we don't have to check those anyway.
- if ((this.binding.returnType.tagBits & TagBits.AnnotationNonNull) == 0) {
- char[][] providedAnnotationName = ((this.binding.returnType.tagBits & TagBits.AnnotationNullable) != 0) ?
- scope.environment().getNullableAnnotationName() : null;
- scope.problemReporter().illegalReturnRedefinition(this, this.descriptor,
- scope.environment().getNonNullAnnotationName(),
- providedAnnotationName, this.binding.returnType);
- }
- }
- }
- }
+ checkNullAnnotations(scope);
this.freeParameters = null; // not used after method lookup
if (checkInvocationArguments(scope, null, this.receiverType, this.binding, null, descriptorParameters, false, this))
@@ -771,6 +737,45 @@ public class ReferenceExpression extends FunctionalExpression implements IPolyEx
return this.resolvedType; // Phew !
}
+ protected void checkNullAnnotations(BlockScope scope) {
+ if (scope.compilerOptions().isAnnotationBasedNullAnalysisEnabled) {
+ if (this.expectedType == null || !NullAnnotationMatching.hasContradictions(this.expectedType)) { // otherwise assume it has been reported and we can do nothing here
+ // TODO: simplify by using this.freeParameters?
+ int len;
+ int expectedlen = this.binding.parameters.length;
+ int providedLen = this.descriptor.parameters.length;
+ if (this.receiverPrecedesParameters)
+ providedLen--; // one parameter is 'consumed' as the receiver
+ boolean isVarArgs = false;
+ if (this.binding.isVarargs()) {
+ isVarArgs = (providedLen == expectedlen)
+ ? !this.descriptor.parameters[expectedlen-1].isCompatibleWith(this.binding.parameters[expectedlen-1])
+ : true;
+ len = providedLen; // binding parameters will be padded from InferenceContext18.getParameter()
+ } else {
+ len = Math.min(expectedlen, providedLen);
+ }
+ for (int i = 0; i < len; i++) {
+ TypeBinding descriptorParameter = this.descriptor.parameters[i + (this.receiverPrecedesParameters ? 1 : 0)];
+ TypeBinding bindingParameter = InferenceContext18.getParameter(this.binding.parameters, i, isVarArgs);
+ NullAnnotationMatching annotationStatus = NullAnnotationMatching.analyse(bindingParameter, descriptorParameter, FlowInfo.UNKNOWN);
+ if (annotationStatus.isAnyMismatch()) {
+ // immediate reporting:
+ scope.problemReporter().referenceExpressionArgumentNullityMismatch(this, bindingParameter, descriptorParameter, this.descriptor, i, annotationStatus);
+ }
+ }
+ TypeBinding returnType = this.binding.returnType;
+ if (this.binding.isConstructor() || this.binding == scope.environment().arrayClone) {
+ returnType = scope.environment().createAnnotatedType(this.receiverType, new AnnotationBinding[]{ scope.environment().getNonNullAnnotation() });
+ }
+ NullAnnotationMatching annotationStatus = NullAnnotationMatching.analyse(this.descriptor.returnType, returnType, FlowInfo.UNKNOWN);
+ if (annotationStatus.isAnyMismatch()) {
+ scope.problemReporter().illegalReturnRedefinition(this, this.descriptor, annotationStatus.isUnchecked(), returnType);
+ }
+ }
+ }
+ }
+
private TypeBinding[] descriptorParametersAsArgumentExpressions() {
if (this.descriptor == null || this.descriptor.parameters == null || this.descriptor.parameters.length == 0)
@@ -950,7 +955,15 @@ public class ReferenceExpression extends FunctionalExpression implements IPolyEx
@Override
public boolean isPotentiallyCompatibleWith(TypeBinding targetType, Scope scope) {
-
+
+ final boolean isConstructorRef = isConstructorReference();
+ if (isConstructorRef && this.receiverType.isArrayType()) {
+ final TypeBinding leafComponentType = this.receiverType.leafComponentType();
+ if (!leafComponentType.isReifiable()) {
+ return false;
+ }
+ }
+
// We get here only when the reference expression is NOT pertinent to applicability.
if (!super.isPertinentToApplicability(targetType, null))
return true;
@@ -980,14 +993,12 @@ public class ReferenceExpression extends FunctionalExpression implements IPolyEx
}
// 15.13.1
- final boolean isMethodReference = isMethodReference();
this.freeParameters = descriptorParameters;
this.checkingPotentialCompatibility = true;
try {
- MethodBinding compileTimeDeclaration =
- this.exactMethodBinding != null ? this.exactMethodBinding :
- isMethodReference ? scope.getMethod(this.receiverType, this.selector, descriptorParameters, this) :
- scope.getConstructor((ReferenceBinding) this.receiverType, descriptorParameters, this);
+ MethodBinding compileTimeDeclaration = this.exactMethodBinding != null ? this.exactMethodBinding : isConstructorRef
+ ? scope.getConstructor((ReferenceBinding) this.receiverType, descriptorParameters, this)
+ : scope.getMethod(this.receiverType, this.selector, descriptorParameters, this);
if (compileTimeDeclaration != null && compileTimeDeclaration.isValidBinding()) // we have the mSMB.
this.potentialMethods = new MethodBinding [] { compileTimeDeclaration };
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 bd01f4043..89e198fec 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -324,6 +324,9 @@ public void resolve(BlockScope scope) {
if (this.expression != null) {
this.expression.setExpressionContext(ASSIGNMENT_CONTEXT);
this.expression.setExpectedType(methodType);
+ if (lambda != null && lambda.argumentsTypeElided() && this.expression instanceof CastExpression) {
+ this.expression.bits |= ASTNode.DisableUnnecessaryCastCheck;
+ }
}
if (methodType == TypeBinding.VOID) {
@@ -370,9 +373,14 @@ public void resolve(BlockScope scope) {
if (expressionType.needsUncheckedConversion(methodType)) {
scope.problemReporter().unsafeTypeConversion(this.expression, expressionType, methodType);
}
- if (this.expression instanceof CastExpression
- && (this.expression.bits & (ASTNode.UnnecessaryCast|ASTNode.DisableUnnecessaryCastCheck)) == 0) {
- CastExpression.checkNeedForAssignedCast(scope, methodType, (CastExpression) this.expression);
+ if (this.expression instanceof CastExpression) {
+ if ((this.expression.bits & (ASTNode.UnnecessaryCast|ASTNode.DisableUnnecessaryCastCheck)) == 0) {
+ CastExpression.checkNeedForAssignedCast(scope, methodType, (CastExpression) this.expression);
+ } else if (lambda != null && lambda.argumentsTypeElided() && (this.expression.bits & ASTNode.UnnecessaryCast) != 0) {
+ if (TypeBinding.equalsEquals(((CastExpression)this.expression).expression.resolvedType, methodType)) {
+ scope.problemReporter().unnecessaryCast((CastExpression)this.expression);
+ }
+ }
}
return;
} else if (isBoxingCompatible(expressionType, methodType, this.expression, scope)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
index db38143a0..1950dde5f 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SingleNameReference.java
@@ -16,8 +16,9 @@
* bug 383368 - [compiler][null] syntactic null analysis for field references
* Bug 412203 - [compiler] Internal compiler error: java.lang.IllegalArgumentException: info cannot be null
* Bug 458396 - NPE in CodeStream.invoke()
+ * Bug 407414 - [compiler][null] Incorrect warning on a primitive type being null
* Jesper S Moller - <jesper@selskabet.org> - Contributions for
- * bug 382721 - [1.8][compiler] Effectively final variables needs special treatment
+ * bug 382721 - [1.8][compiler] Effectively final variables needs special treatment
* bug 378674 - "The method can be declared as static" is wrong
* bug 404657 - [1.8][compiler] Analysis for effectively final variables fails to consider loops
*******************************************************************************/
@@ -901,6 +902,8 @@ public VariableBinding nullAnnotatedVariableBinding(boolean supportTypeAnnotatio
}
public int nullStatus(FlowInfo flowInfo, FlowContext flowContext) {
+ if ((this.implicitConversion & TypeIds.BOXING) != 0)
+ return FlowInfo.NON_NULL;
LocalVariableBinding local = localVariableBinding();
if (local != null) {
return flowInfo.nullStatus(local);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
index 65c07a76b..6b1a1ecaa 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TryStatement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -22,6 +22,8 @@
* bug 402993 - [null] Follow up of bug 401088: Missing warning about redundant null check
* bug 384380 - False positive on a ?? Potential null pointer access ?? after a continue
* Bug 415790 - [compiler][resource]Incorrect potential resource leak warning in for loop with close in try/catch
+ * Bug 371614 - [compiler][resource] Wrong "resource leak" problem on return/throw inside while loop
+ * Bug 444964 - [1.7+][resource] False resource leak warning (try-with-resources for ByteArrayOutputStream - return inside for loop)
* Jesper Steen Moller - Contributions for
* bug 404146 - [1.7][compiler] nested try-catch-finally-blocks leads to unrunnable Java byte code
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
@@ -165,8 +167,8 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
if (resourceBinding.closeTracker != null) {
// this was false alarm, we don't need to track the resource
- this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker);
- // keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block
+ resourceBinding.closeTracker.withdraw();
+ resourceBinding.closeTracker = null;
}
MethodBinding closeMethod = findCloseMethod(resource, resourceBinding);
if (closeMethod != null && closeMethod.isValidBinding() && closeMethod.returnType.id == TypeIds.T_void) {
@@ -279,7 +281,7 @@ public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, Fl
resourceBinding.useFlag = LocalVariableBinding.USED; // Is implicitly used anyways.
if (resourceBinding.closeTracker != null) {
// this was false alarm, we don't need to track the resource
- this.tryBlock.scope.removeTrackingVar(resourceBinding.closeTracker);
+ resourceBinding.closeTracker.withdraw();
// keep the tracking variable in the resourceBinding in order to prevent creating a new one while analyzing the try block
}
MethodBinding closeMethod = findCloseMethod(resource, resourceBinding);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java
index 27b11b37e..87e1254c2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ExceptionHandlingFlowContext.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -11,6 +11,7 @@
* bug 345305 - [compiler][null] Compiler misidentifies a case of "variable can only be null"
* bug 402993 - [null] Follow up of bug 401088: Missing warning about redundant null check
* Bug 453483 - [compiler][null][loop] Improve null analysis for loops
+ * Bug 421035 - [resource] False alarm of resource leak warning when casting a closeable in its assignment
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.flow;
@@ -83,6 +84,7 @@ public ExceptionHandlingFlowContext(
UnconditionalFlowInfo unconditionalCopy = flowInfo.unconditionalCopy();
unconditionalCopy.iNBit = -1L;
unconditionalCopy.iNNBit = -1L;
+ unconditionalCopy.tagBits |= FlowInfo.UNROOTED;
this.initsOnFinally = unconditionalCopy;
}
ExceptionHandlingFlowContext(
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
index 7cecbc2b3..f1e5d4357 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2012 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -14,6 +14,7 @@
* bug 332637 - Dead Code detection removing code that isn't dead
* bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional
* Bug 411964 - [1.8][null] leverage null type annotation in foreach statement
+ * Bug 421035 - [resource] False alarm of resource leak warning when casting a closeable in its assignment
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.flow;
@@ -61,6 +62,8 @@ public abstract class FlowInfo {
public final static int POTENTIALLY_NULL = 16;
public final static int POTENTIALLY_NON_NULL = 32;
+ public final static int UNROOTED = 64; // marks a flowInfo that may be appended to another flowInfo (accepting incoming nulls/nonnulls, see UFI.iNBit/iNNBit).
+
public static final UnconditionalFlowInfo DEAD_END; // Represents a dead branch status of initialization
static {
DEAD_END = new UnconditionalFlowInfo();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
index 210650cf7..3b49f1738 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -23,6 +23,7 @@
* Bug 455557 - [jdt] NPE LoopingFlowContext.recordNullReference
* Bug 455723 - Nonnull argument not correctly inferred in loop
* Bug 415790 - [compiler][resource]Incorrect potential resource leak warning in for loop with close in try/catch
+ * Bug 421035 - [resource] False alarm of resource leak warning when casting a closeable in its assignment
* Jesper S Moller - contributions for
* bug 404657 - [1.8][compiler] Analysis for effectively final variables fails to consider loops
*******************************************************************************/
@@ -417,7 +418,7 @@ public void complainOnDeferredNullChecks(BlockScope scope, FlowInfo callerFlowIn
}
nullStatus = closeTracker.findMostSpecificStatus(flowInfo, scope, null);
closeTracker.recordErrorLocation(this.nullReferences[i], nullStatus);
- closeTracker.reportRecordedErrors(scope, nullStatus);
+ closeTracker.reportRecordedErrors(scope, nullStatus, flowInfo.reachMode() != FlowInfo.REACHABLE);
this.nullReferences[i] = null;
continue;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
index 8b68fd8ad..4e34ec5e8 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
@@ -21,6 +21,7 @@
* bug 394768 - [compiler][resource] Incorrect resource leak warning when creating stream in conditional
* Bug 453483 - [compiler][null][loop] Improve null analysis for loops
* Bug 454031 - [compiler][null][loop] bug in null analysis; wrong "dead code" detection
+ * Bug 421035 - [resource] False alarm of resource leak warning when casting a closeable in its assignment
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.flow;
@@ -440,10 +441,7 @@ public FlowInfo addPotentialInitializationsFrom(FlowInfo inits) {
else if (otherInits.extra != null) {
// no storage here, but other has extra storage.
int otherLength = otherInits.extra[0].length;
- this.extra = new long[extraLength][];
- for (int j = 0; j < extraLength; j++) {
- this.extra[j] = new long[otherLength];
- }
+ createExtraSpace(otherLength);
System.arraycopy(otherInits.extra[1], 0, this.extra[1], 0,
otherLength);
}
@@ -528,10 +526,7 @@ public UnconditionalFlowInfo addPotentialNullInfoFrom(
if (otherInits.extra != null) {
int mergeLimit = 0, copyLimit = otherInits.extra[0].length;
if (this.extra == null) {
- this.extra = new long[extraLength][];
- for (int j = 0; j < extraLength; j++) {
- this.extra[j] = new long[copyLimit];
- }
+ createExtraSpace(copyLimit);
if (COVERAGE_TEST_FLAG) {
if (CoverageTestId == 11) {
throw new AssertionFailedException("COVERAGE 11"); //$NON-NLS-1$
@@ -1188,10 +1183,7 @@ public void markAsComparedEqualToNonNull(LocalVariableBinding local) {
int vectorIndex = (position / BitCacheSize) - 1;
if (this.extra == null) {
int length = vectorIndex + 1;
- this.extra = new long[extraLength][];
- for (int j = 0; j < extraLength; j++) {
- this.extra[j] = new long[length];
- }
+ createExtraSpace(length);
if (COVERAGE_TEST_FLAG) {
if (CoverageTestId == 16) {
throw new AssertionFailedException("COVERAGE 16"); //$NON-NLS-1$
@@ -1287,10 +1279,7 @@ public void markAsComparedEqualToNull(LocalVariableBinding local) {
mask = 1L << (position % BitCacheSize);
if (this.extra == null) {
int length = vectorIndex + 1;
- this.extra = new long[extraLength][];
- for (int j = 0; j < extraLength; j++) {
- this.extra[j] = new long[length ];
- }
+ createExtraSpace(length);
if (COVERAGE_TEST_FLAG) {
if(CoverageTestId == 20) {
throw new AssertionFailedException("COVERAGE 20"); //$NON-NLS-1$
@@ -1355,10 +1344,7 @@ final private void markAsDefinitelyAssigned(int position) {
int vectorIndex = (position / BitCacheSize) - 1;
if (this.extra == null) {
int length = vectorIndex + 1;
- this.extra = new long[extraLength][];
- for (int j = 0; j < extraLength; j++) {
- this.extra[j] = new long[length];
- }
+ createExtraSpace(length);
}
else {
int oldLength; // might need to grow the arrays
@@ -1416,10 +1402,7 @@ public void markAsDefinitelyNonNull(LocalVariableBinding local) {
int vectorIndex = (position / BitCacheSize) - 1;
if (this.extra == null) {
int length = vectorIndex + 1;
- this.extra = new long[extraLength][];
- for (int j = 0; j < extraLength; j++) {
- this.extra[j] = new long[length];
- }
+ createExtraSpace(length);
}
else {
int oldLength; // might need to grow the arrays
@@ -1476,10 +1459,7 @@ public void markAsDefinitelyNull(LocalVariableBinding local) {
int vectorIndex = (position / BitCacheSize) - 1;
if (this.extra == null) {
int length = vectorIndex + 1;
- this.extra = new long[extraLength][];
- for (int j = 0; j < extraLength; j++) {
- this.extra[j] = new long[length];
- }
+ createExtraSpace(length);
}
else {
int oldLength; // might need to grow the arrays
@@ -1543,10 +1523,7 @@ public void markAsDefinitelyUnknown(LocalVariableBinding local) {
int vectorIndex = (position / BitCacheSize) - 1;
if (this.extra == null) {
int length = vectorIndex + 1;
- this.extra = new long[extraLength][];
- for (int j = 0; j < extraLength; j++) {
- this.extra[j] = new long[length];
- }
+ createExtraSpace(length);
}
else {
int oldLength; // might need to grow the arrays
@@ -1632,10 +1609,7 @@ public void markPotentiallyUnknownBit(LocalVariableBinding local) {
int vectorIndex = (position / BitCacheSize) - 1;
if (this.extra == null) {
int length = vectorIndex + 1;
- this.extra = new long[extraLength][];
- for (int j = 0; j < extraLength; j++) {
- this.extra[j] = new long[length];
- }
+ createExtraSpace(length);
}
else {
int oldLength; // might need to grow the arrays
@@ -1682,10 +1656,7 @@ public void markPotentiallyNullBit(LocalVariableBinding local) {
int vectorIndex = (position / BitCacheSize) - 1;
if (this.extra == null) {
int length = vectorIndex + 1;
- this.extra = new long[extraLength][];
- for (int j = 0; j < extraLength; j++) {
- this.extra[j] = new long[length];
- }
+ createExtraSpace(length);
}
else {
int oldLength; // might need to grow the arrays
@@ -1732,10 +1703,7 @@ public void markPotentiallyNonNullBit(LocalVariableBinding local) {
int vectorIndex = (position / BitCacheSize) - 1;
if (this.extra == null) {
int length = vectorIndex + 1;
- this.extra = new long[extraLength][];
- for (int j = 0; j < extraLength; j++) {
- this.extra[j] = new long[length];
- }
+ createExtraSpace(length);
}
else {
int oldLength; // might need to grow the arrays
@@ -2055,6 +2023,7 @@ public UnconditionalFlowInfo nullInfoLessUnconditionalCopy() {
copy.iNBit = -1L;
copy.iNNBit = -1L;
copy.tagBits = this.tagBits & ~NULL_FLAG_MASK;
+ copy.tagBits |= UNROOTED;
copy.maxFieldCount = this.maxFieldCount;
if (this.extra != null) {
int length;
@@ -2215,9 +2184,7 @@ public UnconditionalFlowInfo unconditionalFieldLessCopy() {
}
}
else if (vectorIndex >= 0) {
- for (int j = 0; j < extraLength; j++) {
- copy.extra[j] = new long[length];
- }
+ copy.createExtraSpace(length);
}
if (vectorIndex >= 0) {
mask = ~((1L << (limit % BitCacheSize))-1);
@@ -2261,5 +2228,16 @@ public void resetAssignmentInfo(int position) {
}
}
}
+
+private void createExtraSpace(int length) {
+ this.extra = new long[extraLength][];
+ for (int j = 0; j < extraLength; j++) {
+ this.extra[j] = new long[length];
+ }
+ if ((this.tagBits & UNROOTED) != 0) {
+ Arrays.fill(this.extra[IN], -1L);
+ Arrays.fill(this.extra[INN], -1L);
+ }
+}
}
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 a3bf693d8..29f431146 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
@@ -131,14 +131,14 @@ public abstract class Binding {
public abstract int kind();
/*
* Computes a key that uniquely identifies this binding.
- * Returns null if binding is not a TypeBinding, a MethodBinding, a FieldBinding or a PackageBinding.
+ * Returns null if binding is not a TypeBinding, a MethodBinding, a FieldBinding, a LocalVariableBinding or a PackageBinding (i.e. an ImportBinding).
*/
public char[] computeUniqueKey() {
return computeUniqueKey(true/*leaf*/);
}
/*
* Computes a key that uniquely identifies this binding. Optionally include access flags.
- * Returns null if binding is not a TypeBinding, a MethodBinding, a FieldBinding or a PackageBinding.
+ * Returns null if binding is not a TypeBinding, a MethodBinding, a FieldBinding, a LocalVariableBinding or a PackageBinding (i.e. an ImportBinding)
*/
public char[] computeUniqueKey(boolean isLeaf) {
return null;
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 68b171229..297d3f47a 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, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -20,6 +20,10 @@
* 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
+ * Bug 371614 - [compiler][resource] Wrong "resource leak" problem on return/throw inside while loop
+ * Bug 421035 - [resource] False alarm of resource leak warning when casting a closeable in its assignment
+ * Bug 444964 - [1.7+][resource] False resource leak warning (try-with-resources for ByteArrayOutputStream - return inside for loop)
+ * Bug 396575 - [compiler][resources] Incorrect Errors/Warnings check for potential resource leak when surrounding with try-catch
* 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
@@ -27,10 +31,9 @@
package org.eclipse.jdt.internal.compiler.lookup;
import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import java.util.Set;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.*;
@@ -1212,7 +1215,7 @@ public int registerTrackingVariable(FakedTrackingVariable fakedTrackingVariable)
/** When are no longer interested in this tracking variable - remove it. */
public void removeTrackingVar(FakedTrackingVariable trackingVariable) {
if (trackingVariable.innerTracker != null) {
- removeTrackingVar(trackingVariable.innerTracker);
+ trackingVariable.innerTracker.withdraw();
trackingVariable.innerTracker = null;
}
if (this.trackingVariables != null)
@@ -1242,10 +1245,10 @@ public void checkUnclosedCloseables(FlowInfo flowInfo, FlowContext flowContext,
FakedTrackingVariable returnVar = (location instanceof ReturnStatement) ?
FakedTrackingVariable.getCloseTrackingVariable(((ReturnStatement)location).expression, flowInfo, flowContext) : null;
- Set varSet = new HashSet(this.trackingVariables);
- FakedTrackingVariable trackingVar;
- // pick one outer-most variable from the set at a time
- while ((trackingVar = FakedTrackingVariable.pickVarForReporting(varSet, this, location != null)) != null) {
+ // iterate variables according to the priorities defined in FakedTrackingVariable.IteratorForReporting.Stage
+ Iterator<FakedTrackingVariable> iterator = new FakedTrackingVariable.IteratorForReporting(this.trackingVariables, this, location != null);
+ while (iterator.hasNext()) {
+ FakedTrackingVariable trackingVar = iterator.next();
if (returnVar != null && trackingVar.isResourceBeingReturned(returnVar)) {
continue;
@@ -1270,7 +1273,7 @@ public void checkUnclosedCloseables(FlowInfo flowInfo, FlowContext flowContext,
if (location == null) // at end of block and not definitely unclosed
{
// problems at specific locations: medium priority
- if (trackingVar.reportRecordedErrors(this, status)) // ... report previously recorded errors
+ if (trackingVar.reportRecordedErrors(this, status, flowInfo.reachMode() != FlowInfo.REACHABLE)) // ... report previously recorded errors
continue;
}
if (status == FlowInfo.POTENTIALLY_NULL) {
@@ -1287,12 +1290,6 @@ public void checkUnclosedCloseables(FlowInfo flowInfo, FlowContext flowContext,
for (int i=0; i<this.localIndex; i++)
this.locals[i].closeTracker = null;
this.trackingVariables = null;
- } else {
- int size = this.trackingVariables.size();
- for (int i=0; i<size; i++) {
- FakedTrackingVariable tracker = (FakedTrackingVariable) this.trackingVariables.get(i);
- tracker.resetReportingBits();
- }
}
}
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 5e987f8ca..4ccb2663c 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
@@ -14,6 +14,7 @@
* Bug 441797 - [1.8] synchronize type annotations on capture and its wildcard
* Bug 456497 - [1.8][null] during inference nullness from target type is lost against weaker hint from applicability analysis
* Bug 456924 - StackOverflowError during compilation
+ * Bug 462790 - [null] NPE in Expression.computeConversion()
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -49,6 +50,7 @@ public class CaptureBinding extends TypeVariableBinding {
this.end = end;
this.captureID = captureID;
this.tagBits |= TagBits.HasCapturedWildcard;
+ this.cud = cud;
if (wildcard.hasTypeAnnotations()) {
// register an unannoted version before adding the annotated wildcard:
CaptureBinding unannotated = (CaptureBinding) clone(null);
@@ -64,7 +66,6 @@ public class CaptureBinding extends TypeVariableBinding {
} else {
computeId(this.environment);
}
- this.cud = cud;
}
// for subclass CaptureBinding18
@@ -440,6 +441,26 @@ public class CaptureBinding extends TypeVariableBinding {
return this.wildcard;
}
+ /*
+ * CaptureBinding needs even more propagation, because we are creating a naked type
+ * (during CaptureBinding(WildcardBinding,ReferenceBinding,int,int,ASTNode,int)
+ * that has no firstBound / superclass / superInterfaces set.
+ */
+ @Override
+ protected TypeBinding[] getDerivedTypesForDeferredInitialization() {
+ TypeBinding[] derived = this.environment.typeSystem.getDerivedTypes(this);
+ if (derived.length > 0) {
+ int count = 0;
+ for (int i = 0; i < derived.length; i++) {
+ if (derived[i] != null && derived[i].id == this.id)
+ derived[count++] = derived[i];
+ }
+ if (count < derived.length)
+ System.arraycopy(derived, 0, derived = new TypeBinding[count], 0, count);
+ }
+ return derived;
+ }
+
public String toString() {
if (this.wildcard != null) {
StringBuffer buffer = new StringBuffer(10);
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 508c72d06..f76562d7f 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, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -22,6 +22,7 @@
* Bug 429958 - [1.8][null] evaluate new DefaultLocation attribute of @NonNullByDefault
* Bug 434570 - Generic type mismatch for parametrized class annotation attribute with inner class
* Bug 444024 - [1.8][compiler][null] Type mismatch error in annotation generics assignment which happens "sometimes"
+ * Bug 459967 - [null] compiler should know about nullness of special methods like MyEnum.valueOf()
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 415821 - [1.8][compiler] CLASS_EXTENDS target type annotation missing for anonymous classes
* het@google.com - Bug 456986 - Bogus error when annotation processor generates annotation type
@@ -617,6 +618,12 @@ public class ClassScope extends Scope {
fields[i].modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
}
}
+ if (isEnum && compilerOptions().isAnnotationBasedNullAnalysisEnabled) {
+ // mark return types of values & valueOf as nonnull (needed to wait till after setMethods() to avoid reentrance):
+ LookupEnvironment environment = this.environment();
+ ((SyntheticMethodBinding)methodBindings[0]).markNonNull(environment);
+ ((SyntheticMethodBinding)methodBindings[1]).markNonNull(environment);
+ }
}
//{ObjectTeams: accessible to sub-class:
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
index ee19b24b8..1056a1c71 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java
@@ -40,6 +40,7 @@
* Bug 446434 - [1.8][null] Enable interned captures also when analysing null type annotations
* Bug 435805 - [1.8][compiler][null] Java 8 compiler does not recognize declaration style null annotations
* Bug 456508 - Unexpected RHS PolyTypeBinding for: <code-snippet>
+ * Bug 390064 - [compiler][resource] Resource leak warning missing when extending parameterized class
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -102,6 +103,7 @@ public class ParameterizedTypeBinding extends ReferenceBinding implements Substi
if (enclosingType != null && enclosingType.hasNullTypeAnnotations())
this.tagBits |= TagBits.HasNullTypeAnnotation;
this.tagBits |= TagBits.HasUnresolvedTypeVariables; // cleared in resolve()
+ this.typeBits = type.typeBits;
}
/**
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 61007e115..e436088a1 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -36,9 +36,12 @@
* Bug 440759 - [1.8][null] @NonNullByDefault should never affect wildcards and uses of a type variable
* Bug 452788 - [1.8][compiler] Type not correctly inferred in lambda expression
* Bug 446442 - [1.8] merge null annotations from super methods
+ * Bug 456532 - [1.8][null] ReferenceBinding.appendNullAnnotation() includes phantom annotations in error messages
* 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
+ * Ulrich Grave <ulrich.grave@gmx.de> - Contributions for
+ * bug 386692 - Missing "unused" warning on "autowired" fields
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -1026,10 +1029,20 @@ public void computeId() {
}
break;
case 6:
- if (!CharOperation.equals(TypeConstants.JDT, this.compoundName[2]) || !CharOperation.equals(TypeConstants.ITYPEBINDING, this.compoundName[5]))
- return;
- if (CharOperation.equals(TypeConstants.ORG_ECLIPSE_JDT_CORE_DOM_ITYPEBINDING, this.compoundName))
- this.typeBits |= TypeIds.BitUninternedType;
+ if (CharOperation.equals(TypeConstants.ORG, this.compoundName[0])) {
+ if (CharOperation.equals(TypeConstants.SPRING, this.compoundName[1])) {
+ if (CharOperation.equals(TypeConstants.AUTOWIRED, this.compoundName[5])) {
+ if (CharOperation.equals(TypeConstants.ORG_SPRING_AUTOWIRED, this.compoundName)) {
+ this.id = TypeIds.T_OrgSpringframeworkBeansFactoryAnnotationAutowired;
+ }
+ }
+ return;
+ }
+ if (!CharOperation.equals(TypeConstants.JDT, this.compoundName[2]) || !CharOperation.equals(TypeConstants.ITYPEBINDING, this.compoundName[5]))
+ return;
+ if (CharOperation.equals(TypeConstants.ORG_ECLIPSE_JDT_CORE_DOM_ITYPEBINDING, this.compoundName))
+ this.typeBits |= TypeIds.BitUninternedType;
+ }
break;
case 7 :
if (!CharOperation.equals(TypeConstants.JDT, this.compoundName[2]) || !CharOperation.equals(TypeConstants.TYPEBINDING, this.compoundName[6]))
@@ -2051,15 +2064,24 @@ public char[] readableName() /*java.lang.Object, p.X<T> */ {
protected void appendNullAnnotation(StringBuffer nameBuffer, CompilerOptions options) {
if (options.isAnnotationBasedNullAnalysisEnabled) {
- // restore applied null annotation from tagBits:
- if ((this.tagBits & TagBits.AnnotationNonNull) != 0) {
- char[][] nonNullAnnotationName = options.nonNullAnnotationName;
- nameBuffer.append('@').append(nonNullAnnotationName[nonNullAnnotationName.length-1]).append(' ');
- }
- if ((this.tagBits & TagBits.AnnotationNullable) != 0) {
- char[][] nullableAnnotationName = options.nullableAnnotationName;
- nameBuffer.append('@').append(nullableAnnotationName[nullableAnnotationName.length-1]).append(' ');
- }
+ if (options.usesNullTypeAnnotations()) {
+ for (AnnotationBinding annotation : this.typeAnnotations) {
+ TypeBinding annotationType = annotation.getAnnotationType();
+ if (annotationType.id == TypeIds.T_ConfiguredAnnotationNonNull || annotation.type.id == TypeIds.T_ConfiguredAnnotationNullable) {
+ nameBuffer.append('@').append(annotationType.shortReadableName()).append(' ');
+ }
+ }
+ } else {
+ // restore applied null annotation from tagBits:
+ if ((this.tagBits & TagBits.AnnotationNonNull) != 0) {
+ char[][] nonNullAnnotationName = options.nonNullAnnotationName;
+ nameBuffer.append('@').append(nonNullAnnotationName[nonNullAnnotationName.length-1]).append(' ');
+ }
+ if ((this.tagBits & TagBits.AnnotationNullable) != 0) {
+ char[][] nullableAnnotationName = options.nullableAnnotationName;
+ nameBuffer.append('@').append(nullableAnnotationName[nullableAnnotationName.length-1]).append(' ');
+ }
+ }
}
}
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 032efd519..51b02a788 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
@@ -1713,13 +1713,13 @@ public abstract class Scope {
ObjectVector found = new ObjectVector(3);
CompilationUnitScope unitScope = compilationUnitScope();
unitScope.recordTypeReferences(argumentTypes);
-
+ List<TypeBinding> visitedTypes = new ArrayList<TypeBinding>();
if (receiverTypeIsInterface) {
unitScope.recordTypeReference(receiverType);
MethodBinding[] receiverMethods = receiverType.getMethods(selector, argumentTypes.length);
if (receiverMethods.length > 0)
found.addAll(receiverMethods);
- findMethodInSuperInterfaces(receiverType, selector, found, null, invocationSite);
+ findMethodInSuperInterfaces(receiverType, selector, found, visitedTypes, invocationSite);
//{ObjectTeams: confined types don't proceed to java.lang.Object:
if (!(TypeAnalyzer.isConfined(receiverType)))
// SH}
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 c108d8b57..c1c2ede8c 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
@@ -26,6 +26,7 @@
* bug 391376 - [1.8] check interaction of default methods with bridge methods and generics
* 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 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
* Bug 415850 - [1.8] Ensure RunJDTCoreTests can cope with null annotations enabled
* Bug 416172 - [1.8][compiler][null] null type annotation not evaluated on method return type
* Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
@@ -1158,16 +1159,27 @@ public char[] computeUniqueKey(boolean isLeaf) {
return uniqueKey;
}
-//{ObjectTeams: allow access from Dependencies:
-public
-// SH}
-void faultInTypesForFieldsAndMethods() {
- if (!isPrototype()) throw new IllegalStateException();
+private void checkAnnotationsInType() {
// check @Deprecated annotation
getAnnotationTagBits(); // marks as deprecated by side effect
ReferenceBinding enclosingType = enclosingType();
if (enclosingType != null && enclosingType.isViewedAsDeprecated() && !isDeprecated())
this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
+
+ for (int i = 0, length = this.memberTypes.length; i < length; i++)
+ ((SourceTypeBinding) this.memberTypes[i]).checkAnnotationsInType();
+}
+
+//{ObjectTeams: allow access from Dependencies:
+public
+// SH}
+void faultInTypesForFieldsAndMethods() {
+ if (!isPrototype()) throw new IllegalStateException();
+ checkAnnotationsInType();
+ internalFaultInTypeForFieldsAndMethods();
+}
+
+private void internalFaultInTypeForFieldsAndMethods() {
fields();
methods();
@@ -1180,7 +1192,7 @@ void faultInTypesForFieldsAndMethods() {
for (int i = 0; i < this.memberTypes.length; i++)
if (!this.memberTypes[i].isBinaryBinding()) // roles could be binary contained in source
//carp}
- ((SourceTypeBinding) this.memberTypes[i]).faultInTypesForFieldsAndMethods();
+ ((SourceTypeBinding) this.memberTypes[i]).internalFaultInTypeForFieldsAndMethods();
}
// NOTE: the type of each field of a source type is resolved when needed
public FieldBinding[] fields() {
@@ -2519,7 +2531,7 @@ public MethodBinding resolveTypesFor(MethodBinding method, boolean fromSynthetic
arg.type.resolvedType :
arg.type.resolveType(methodDecl.scope, true /* check bounds*/);
// orig:
-// parameterType = arg.type.resolveType(methodDecl.scope, true /* check bounds*/);
+// parameterType = arg.type.resolveType(methodDecl.scope, true /* check bounds*/);
} finally {
if (deferRawTypeCheck) {
arg.type.bits &= ~ASTNode.IgnoreRawTypeCheck;
@@ -2755,8 +2767,7 @@ private void createArgumentBindings(MethodBinding method, CompilerOptions compil
methodDecl.createArgumentBindings();
// add implicit annotations (inherited(?) & default):
if (compilerOptions.isAnnotationBasedNullAnalysisEnabled) {
- new ImplicitNullAnnotationVerifier(this.scope.environment(), compilerOptions.inheritNullAnnotations)
- .checkImplicitNullAnnotations(method, methodDecl, true, this.scope);
+ new ImplicitNullAnnotationVerifier(this.scope.environment()).checkImplicitNullAnnotations(method, methodDecl, true, this.scope);
}
}
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
index 73a188d34..133ff4313 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -11,6 +11,7 @@
* Technical University Berlin - extended API and implementation
* Stephan Herrmann - Contribution for
* bug 400710 - [1.8][compiler] synthetic access to default method generates wrong code
+ * Bug 459967 - [null] compiler should know about nullness of special methods like MyEnum.valueOf()
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas
*******************************************************************************/
@@ -458,6 +459,14 @@ public class SyntheticMethodBinding extends MethodBinding {
this.modifiers = ClassFileConstants.AccSynthetic | ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic;
this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved);
this.returnType = arrayType;
+ LookupEnvironment environment = declaringClass.environment;
+ if (environment.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
+ // mark X[]::new and X[]::clone as returning 'X @NonNull' (don't wait (cf. markNonNull()), because we're called as late as codeGen):
+ if (environment.usesNullTypeAnnotations())
+ this.returnType = environment.createAnnotatedType(this.returnType, new AnnotationBinding[]{ environment.getNonNullAnnotation() });
+ else
+ this.tagBits |= TagBits.AnnotationNonNull;
+ }
this.parameters = new TypeBinding[] { purpose == SyntheticMethodBinding.ArrayConstructor ? TypeBinding.INT : (TypeBinding) arrayType};
this.thrownExceptions = Binding.NO_EXCEPTIONS;
this.purpose = purpose;
@@ -673,4 +682,27 @@ public class SyntheticMethodBinding extends MethodBinding {
public LambdaExpression sourceLambda() {
return this.lambda;
}
+
+ public void markNonNull(LookupEnvironment environment) {
+ // deferred update of the return type
+ switch (this.purpose) {
+ case EnumValues:
+ if (environment.usesNullTypeAnnotations()) {
+ TypeBinding elementType = ((ArrayBinding)this.returnType).leafComponentType();
+ AnnotationBinding nonNullAnnotation = environment.getNonNullAnnotation();
+ elementType = environment.createAnnotatedType(elementType, new AnnotationBinding[]{ environment.getNonNullAnnotation() });
+ this.returnType = environment.createArrayType(elementType, 1, new AnnotationBinding[]{ nonNullAnnotation, null });
+ } else {
+ this.tagBits |= TagBits.AnnotationNonNull;
+ }
+ return;
+ case EnumValueOf:
+ if (environment.usesNullTypeAnnotations()) {
+ this.returnType = environment.createAnnotatedType(this.returnType, new AnnotationBinding[]{ environment.getNonNullAnnotation() });
+ } else {
+ this.tagBits |= TagBits.AnnotationNonNull;
+ }
+ return;
+ }
+ }
}
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 c9611a285..0284bd1c6 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -22,6 +22,8 @@
* Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
* Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for
* Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas
+ * Ulrich Grave <ulrich.grave@gmx.de> - Contributions for
+ * bug 386692 - Missing "unused" warning on "autowired" fields
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -119,6 +121,7 @@ public interface TypeConstants {
char[] TYPEBINDING = "TypeBinding".toCharArray(); //$NON-NLS-1$
char[] DOM = "dom".toCharArray(); //$NON-NLS-1$
char[] ITYPEBINDING = "ITypeBinding".toCharArray(); //$NON-NLS-1$
+ char[] SPRING = "springframework".toCharArray(); //$NON-NLS-1$
// Constant compound names
char[][] JAVA_LANG = {JAVA, LANG};
@@ -330,6 +333,13 @@ public interface TypeConstants {
// detail for the above:
char[] OPTIONAL = "optional".toCharArray(); //$NON-NLS-1$
+ // Spring @Autowired annotation
+ char [] AUTOWIRED = "Autowired".toCharArray(); //$NON-NLS-1$
+ char [] BEANS = "beans".toCharArray(); //$NON-NLS-1$
+ char [] FACTORY = "factory".toCharArray(); //$NON-NLS-1$
+ char[][] ORG_SPRING_AUTOWIRED = new char[][] {ORG, SPRING, BEANS, FACTORY, ANNOTATION, AUTOWIRED};
+ char[] REQUIRED = "required".toCharArray(); //$NON-NLS-1$
+
// Constraints for generic type argument inference
int CONSTRAINT_EQUAL = 0; // Actual = Formal
int CONSTRAINT_EXTENDS = 1; // Actual << Formal
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
index cc7114813..1693a6587 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeIds.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -16,6 +16,8 @@
* bug 382069 - [null] Make the null analysis consider JUnit's assertNotNull similarly to assertions
* Jesper S Moller <jesper@selskabet.org> - Contributions for
* Bug 412153 - [1.8][compiler] Check validity of annotations which may be repeatable
+ * Ulrich Grave <ulrich.grave@gmx.de> - Contributions for
+ * bug 386692 - Missing "unused" warning on "autowired" fields
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -127,11 +129,16 @@ public interface TypeIds {
// new in 3.9 to identify known @Inject annotations
final int T_JavaxInjectInject = 80;
final int T_ComGoogleInjectInject = 81;
+
+ // @Autowired
+ final int T_OrgSpringframeworkBeansFactoryAnnotationAutowired = 82;
+
// Java 8 - JEP 120
final int T_JavaLangAnnotationRepeatable = 90;
// If you add new type id, make sure to bump up T_LastWellKnownTypeId if there is a cross over.
final int T_LastWellKnownTypeId = 128;
+
final int NoId = Integer.MAX_VALUE;
public static final int IMPLICIT_CONVERSION_MASK = 0xFF;
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 c1abf5241..df7902024 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
@@ -33,6 +33,8 @@
* Bug 456497 - [1.8][null] during inference nullness from target type is lost against weaker hint from applicability analysis
* Bug 456459 - Discrepancy between Eclipse compiler and javac - Enums, interfaces, and generics
* Bug 456487 - [1.8][null] @Nullable type variant of @NonNull-constrained type parameter causes grief
+ * Bug 462790 - [null] NPE in Expression.computeConversion()
+ * Bug 456532 - [1.8][null] ReferenceBinding.appendNullAnnotation() includes phantom annotations in error messages
*******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;
@@ -944,6 +946,27 @@ public class TypeVariableBinding extends ReferenceBinding {
return readableName;
}
+ protected void appendNullAnnotation(StringBuffer nameBuffer, CompilerOptions options) {
+ int oldSize = nameBuffer.length();
+ super.appendNullAnnotation(nameBuffer, options);
+ if (oldSize == nameBuffer.length()) { // nothing appended in super.appendNullAnnotation()?
+ if (hasNullTypeAnnotations()) {
+ // see if the prototype has null type annotations:
+ TypeVariableBinding[] typeVariables = null;
+ if (this.declaringElement instanceof ReferenceBinding) {
+ typeVariables = ((ReferenceBinding) this.declaringElement).typeVariables();
+ } else if (this.declaringElement instanceof MethodBinding) {
+ typeVariables = ((MethodBinding) this.declaringElement).typeVariables();
+ }
+ if (typeVariables != null && typeVariables.length > this.rank) {
+ TypeVariableBinding prototype = typeVariables[this.rank];
+ if (prototype != this)//$IDENTITY-COMPARISON$
+ prototype.appendNullAnnotation(nameBuffer, options);
+ }
+ }
+ }
+ }
+
public TypeBinding unannotated() {
return this.hasTypeAnnotations() ? this.environment.getUnannotatedType(this) : this;
}
@@ -1032,10 +1055,11 @@ public class TypeVariableBinding extends ReferenceBinding {
public TypeBinding setFirstBound(TypeBinding firstBound) {
this.firstBound = firstBound;
if ((this.tagBits & TagBits.HasAnnotatedVariants) != 0) {
- TypeBinding [] annotatedTypes = this.environment.getAnnotatedTypes(this);
+ TypeBinding [] annotatedTypes = getDerivedTypesForDeferredInitialization();
for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) {
TypeVariableBinding annotatedType = (TypeVariableBinding) annotatedTypes[i];
- annotatedType.firstBound = firstBound;
+ if (annotatedType.firstBound == null)
+ annotatedType.firstBound = firstBound;
}
}
if (firstBound != null && firstBound.hasNullTypeAnnotations())
@@ -1048,10 +1072,11 @@ public class TypeVariableBinding extends ReferenceBinding {
public ReferenceBinding setSuperClass(ReferenceBinding superclass) {
this.superclass = superclass;
if ((this.tagBits & TagBits.HasAnnotatedVariants) != 0) {
- TypeBinding [] annotatedTypes = this.environment.getAnnotatedTypes(this);
+ TypeBinding [] annotatedTypes = getDerivedTypesForDeferredInitialization();
for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) {
TypeVariableBinding annotatedType = (TypeVariableBinding) annotatedTypes[i];
- annotatedType.superclass = superclass;
+ if (annotatedType.superclass == null)
+ annotatedType.superclass = superclass;
}
}
return superclass;
@@ -1062,15 +1087,20 @@ public class TypeVariableBinding extends ReferenceBinding {
public ReferenceBinding [] setSuperInterfaces(ReferenceBinding[] superInterfaces) {
this.superInterfaces = superInterfaces;
if ((this.tagBits & TagBits.HasAnnotatedVariants) != 0) {
- TypeBinding [] annotatedTypes = this.environment.getAnnotatedTypes(this);
+ TypeBinding [] annotatedTypes = getDerivedTypesForDeferredInitialization();
for (int i = 0, length = annotatedTypes == null ? 0 : annotatedTypes.length; i < length; i++) {
TypeVariableBinding annotatedType = (TypeVariableBinding) annotatedTypes[i];
- annotatedType.superInterfaces = superInterfaces;
+ if (annotatedType.superInterfaces == null)
+ annotatedType.superInterfaces = superInterfaces;
}
}
return superInterfaces;
}
+ protected TypeBinding[] getDerivedTypesForDeferredInitialization() {
+ return this.environment.getAnnotatedTypes(this);
+ }
+
public TypeBinding combineTypeAnnotations(TypeBinding substitute) {
if (hasTypeAnnotations()) {
// may need to merge annotations from the original variable and from substitution:
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 fd36d240f..689813bb3 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
@@ -59,6 +59,8 @@
* Bug 446442 - [1.8] merge null annotations from super methods
* Bug 455723 - Nonnull argument not correctly inferred in loop
* Bug 458361 - [1.8][null] reconciler throws NPE in ProblemReporter.illegalReturnRedefinition()
+ * Bug 459967 - [null] compiler should know about nullness of special methods like MyEnum.valueOf()
+ * Bug 461878 - [1.7][1.8][compiler][null] ECJ compiler does not allow to use null annotations on annotations
* 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
@@ -68,6 +70,8 @@
* bug 419209 - [1.8] Repeating container annotations should be rejected in the presence of annotation it contains
* Bug 429384 - [1.8][null] implement conformance rules for null-annotated lower / upper type bounds
* Bug 416182 - [1.8][compiler][null] Contradictory null annotations not rejected
+ * Ulrich Grave <ulrich.grave@gmx.de> - Contributions for
+ * bug 386692 - Missing "unused" warning on "autowired" fields
********************************************************************************/
package org.eclipse.jdt.internal.compiler.problem;
@@ -6366,8 +6370,15 @@ public void nullAnnotationUnsupportedLocation(Annotation annotation) {
String[] shortArguments = new String[] {
String.valueOf(annotation.resolvedType.shortReadableName())
};
+ int severity = ProblemSeverities.Error | ProblemSeverities.Fatal;
+ if (annotation.recipient instanceof ReferenceBinding) {
+ if (((ReferenceBinding) annotation.recipient).isAnnotationType())
+ severity = ProblemSeverities.Warning; // special case for https://bugs.eclipse.org/461878
+ }
handle(IProblem.NullAnnotationUnsupportedLocation,
- arguments, shortArguments, annotation.sourceStart, annotation.sourceEnd);
+ arguments, shortArguments,
+ severity,
+ annotation.sourceStart, annotation.sourceEnd);
}
public void nullAnnotationUnsupportedLocation(TypeReference type) {
int sourceEnd = type.sourceEnd;
@@ -9527,6 +9538,7 @@ private boolean excludeDueToAnnotation(Annotation[] annotations, int problemId)
break;
case TypeIds.T_JavaxInjectInject:
case TypeIds.T_ComGoogleInjectInject:
+ case TypeIds.T_OrgSpringframeworkBeansFactoryAnnotationAutowired:
if (problemId != IProblem.UnusedPrivateField)
return true; // @Inject on method/ctor does constitute a relevant use, just on fields it doesn't
break;
@@ -13802,8 +13814,7 @@ public void referenceExpressionArgumentNullityMismatch(ReferenceExpression locat
location.sourceEnd);
}
public void illegalReturnRedefinition(ASTNode location, MethodBinding descriptorMethod,
- char[][] nonNullAnnotationName,
- char/*@Nullable*/[][] providedAnnotationName, TypeBinding providedType) {
+ boolean isUnchecked, TypeBinding providedType) {
StringBuffer methodSignature = new StringBuffer()
.append(descriptorMethod.declaringClass.readableName())
.append('.')
@@ -13812,22 +13823,16 @@ public void illegalReturnRedefinition(ASTNode location, MethodBinding descriptor
.append(descriptorMethod.declaringClass.shortReadableName())
.append('.')
.append(descriptorMethod.shortReadableName());
- StringBuffer providedPrefix = new StringBuffer();
- StringBuffer providedShortPrefix = new StringBuffer();
- if (providedAnnotationName != null) {
- providedPrefix.append('@').append(CharOperation.toString(providedAnnotationName)).append(' ');
- providedShortPrefix.append('@').append(providedAnnotationName[providedAnnotationName.length-1]).append(' ');
- }
this.handle(
- providedAnnotationName == null
+ isUnchecked
? IProblem.ReferenceExpressionReturnNullRedefUnchecked
: IProblem.ReferenceExpressionReturnNullRedef,
new String[] { methodSignature.toString(),
- CharOperation.toString(nonNullAnnotationName), String.valueOf(descriptorMethod.returnType.readableName()),
- providedPrefix.toString(), String.valueOf(providedType.readableName())},
+ String.valueOf(descriptorMethod.returnType.nullAnnotatedReadableName(this.options, false)),
+ String.valueOf(providedType.nullAnnotatedReadableName(this.options, false))},
new String[] { shortSignature.toString(),
- String.valueOf(nonNullAnnotationName[nonNullAnnotationName.length-1]), String.valueOf(descriptorMethod.returnType.shortReadableName()),
- providedShortPrefix.toString(), String.valueOf(providedType.shortReadableName())},
+ String.valueOf(descriptorMethod.returnType.nullAnnotatedReadableName(this.options, true)),
+ String.valueOf(providedType.nullAnnotatedReadableName(this.options, true))},
location.sourceStart,
location.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 c8fe88603..c1fdaa424 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
@@ -817,8 +817,8 @@
956 = Null type safety (type annotations): The expression of type ''{1}'' needs unchecked conversion to conform to ''{0}'', corresponding supertype is ''{2}''
957 = Null type mismatch at parameter {0}: required ''{1}'' but provided ''{2}'' via method descriptor {3}
958 = Null type safety: parameter {0} provided via method descriptor {3} needs unchecked conversion to conform to ''{1}''
-959 = Null type mismatch at method return type: Method descriptor {0} promises ''@{1} {2}'' but referenced method provides ''{3}{4}''
-960 = Null type safety at method return type: Method descriptor {0} promises ''@{1} {2}'' but referenced method provides ''{3}{4}''
+959 = Null type mismatch at method return type: Method descriptor {0} promises ''{1}'' but referenced method provides ''{2}''
+960 = Null type safety at method return type: Method descriptor {0} promises ''{1}'' but referenced method provides ''{2}''
961 = Redundant null check: comparing ''{0}'' against null
962 = The nullness annotation ''{0}'' is not applicable at this location
963 = Nullness annotations are not applicable at this location
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
index 151d5da00..74844ebf7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 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
@@ -1115,7 +1115,14 @@ public class Util implements SuffixConstants {
}
}
} else if (typeBinding.isNestedType()) {
- classFile.recordInnerClasses(typeBinding);
+ TypeBinding enclosingType = typeBinding;
+ do {
+ if (!enclosingType.canBeSeenBy(classFile.referenceBinding.scope))
+ break;
+ enclosingType = enclosingType.enclosingType();
+ } while (enclosingType != null);
+ if (enclosingType == null)
+ classFile.recordInnerClasses(typeBinding);
}
}
/*

Back to the top