Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/NullAnnotationsRewriteOperations.java')
-rw-r--r--org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/NullAnnotationsRewriteOperations.java137
1 files changed, 103 insertions, 34 deletions
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/NullAnnotationsRewriteOperations.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/NullAnnotationsRewriteOperations.java
index adb1fe7b63..f0074bf92a 100644
--- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/NullAnnotationsRewriteOperations.java
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/NullAnnotationsRewriteOperations.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2012 GK Software AG and others.
+ * Copyright (c) 2011, 2013 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
@@ -25,11 +25,11 @@ import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
-import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.IAnnotationBinding;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IExtendedModifier;
+import org.eclipse.jdt.core.dom.IMemberValuePairBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
@@ -58,10 +58,19 @@ import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
public class NullAnnotationsRewriteOperations {
+ public enum ChangeKind {
+ LOCAL, // do the normal thing locally in the current method
+ INVERSE, // insert the inverse annotation in the local method
+ OVERRIDDEN, // change the overridden method
+ TARGET // change the target method of a method call
+ }
+
static abstract class SignatureAnnotationRewriteOperation extends CompilationUnitRewriteOperation {
String fAnnotationToAdd;
String fAnnotationToRemove;
boolean fAllowRemove;
+ boolean fRemoveIfNonNullByDefault;
+ String fNonNullByDefaultName;
CompilationUnit fUnit;
protected String fKey;
protected String fMessage;
@@ -97,6 +106,37 @@ public class NullAnnotationsRewriteOperations {
return true;
}
+ /* Is the given element affected by a @NonNullByDefault. */
+ boolean hasNonNullDefault(IBinding enclosingElement) {
+ if (!fRemoveIfNonNullByDefault) return false;
+ IAnnotationBinding[] annotations = enclosingElement.getAnnotations();
+ for (int i= 0; i < annotations.length; i++) {
+ IAnnotationBinding annot = annotations[i];
+ if (annot.getAnnotationType().getQualifiedName().equals(fNonNullByDefaultName)) {
+ IMemberValuePairBinding[] pairs= annot.getDeclaredMemberValuePairs();
+ if (pairs.length > 0) {
+ // is default cancelled by "false" or "value=false" ?
+ for (int j= 0; j < pairs.length; j++)
+ if (pairs[j].getKey() == null || pairs[j].getKey().equals("value")) //$NON-NLS-1$
+ return (pairs[j].getValue() != Boolean.FALSE);
+ }
+ return true;
+ }
+ }
+ if (enclosingElement instanceof IMethodBinding) {
+ return hasNonNullDefault(((IMethodBinding)enclosingElement).getDeclaringClass());
+ } else if (enclosingElement instanceof ITypeBinding) {
+ ITypeBinding typeBinding= (ITypeBinding)enclosingElement;
+ if (typeBinding.isLocal())
+ return hasNonNullDefault(typeBinding.getDeclaringMethod());
+ else if (typeBinding.isMember())
+ return hasNonNullDefault(typeBinding.getDeclaringClass());
+ else
+ return hasNonNullDefault(typeBinding.getPackage());
+ }
+ return false;
+ }
+
public String getMessage() {
return fMessage;
}
@@ -109,7 +149,7 @@ public class NullAnnotationsRewriteOperations {
*/
static class ReturnAnnotationRewriteOperation extends SignatureAnnotationRewriteOperation {
- private final BodyDeclaration fBodyDeclaration;
+ private final MethodDeclaration fBodyDeclaration;
ReturnAnnotationRewriteOperation(CompilationUnit unit, MethodDeclaration method, String annotationToAdd, String annotationToRemove, boolean allowRemove, String message) {
fUnit= unit;
@@ -128,6 +168,8 @@ public class NullAnnotationsRewriteOperations {
TextEditGroup group= createTextEditGroup(fMessage, cuRewrite);
if (!checkExisting(fBodyDeclaration.modifiers(), listRewrite, group))
return;
+ if (hasNonNullDefault(fBodyDeclaration.resolveBinding()))
+ return; // should be safe, as in this case checkExisting() should've already produced a change (remove existing annotation).
Annotation newAnnotation= ast.newMarkerAnnotation();
ImportRewrite importRewrite= cuRewrite.getImportRewrite();
String resolvableName= importRewrite.addImport(fAnnotationToAdd);
@@ -241,9 +283,15 @@ public class NullAnnotationsRewriteOperations {
// Entry for QuickFixes:
public static SignatureAnnotationRewriteOperation createAddAnnotationOperation(CompilationUnit compilationUnit, IProblemLocation problem, String annotationToAdd, String annotationToRemove,
- Set<String> handledPositions, boolean thisUnitOnly, boolean allowRemove, boolean modifyOverridden) {
- SignatureAnnotationRewriteOperation result= modifyOverridden ? createAddAnnotationToOverriddenOperation(compilationUnit, problem, annotationToAdd, annotationToRemove, handledPositions,
- thisUnitOnly, allowRemove) : createAddAnnotationOperation(compilationUnit, problem, annotationToAdd, annotationToRemove, handledPositions, thisUnitOnly, allowRemove);
+ Set<String> handledPositions, boolean thisUnitOnly, boolean allowRemove, boolean isArgumentProblem, ChangeKind changeKind) {
+ // precondition:
+ // thisUnitOnly => changeKind == LOCAL
+ SignatureAnnotationRewriteOperation result;
+ if (changeKind == ChangeKind.OVERRIDDEN)
+ result= createAddAnnotationToOverriddenOperation(compilationUnit, problem, annotationToAdd, annotationToRemove, allowRemove);
+ else
+ result= createAddAnnotationOperation(compilationUnit, problem, annotationToAdd, annotationToRemove, changeKind == ChangeKind.TARGET,
+ thisUnitOnly, allowRemove, isArgumentProblem);
if (handledPositions != null && result != null) {
if (handledPositions.contains(result.getKey()))
return null;
@@ -253,7 +301,7 @@ public class NullAnnotationsRewriteOperations {
}
private static SignatureAnnotationRewriteOperation createAddAnnotationOperation(CompilationUnit compilationUnit, IProblemLocation problem, String annotationToAdd, String annotationToRemove,
- Set<String> handledPositions, boolean thisUnitOnly, boolean allowRemove) {
+ boolean changeTargetMethod, boolean thisUnitOnly, boolean allowRemove, boolean isArgumentProblem) {
ICompilationUnit cu= (ICompilationUnit) compilationUnit.getJavaElement();
if (!JavaModelUtil.is50OrHigher(cu.getJavaProject()))
return null;
@@ -274,7 +322,7 @@ public class NullAnnotationsRewriteOperations {
break; // do propose changes even if we already have an annotation
default:
// if this method has annotations, don't change'em
- if (NullAnnotationsFix.hasExplicitNullAnnotation(cu, problem.getOffset()))
+ if (!allowRemove && NullAnnotationsFix.hasExplicitNullAnnotation(cu, problem.getOffset()))
return null;
}
@@ -284,21 +332,38 @@ public class NullAnnotationsRewriteOperations {
annotationNameLabel= annotationToAdd.substring(lastDot + 1);
annotationNameLabel= BasicElementLabels.getJavaElementName(annotationNameLabel);
- if (selectedNode.getParent() instanceof MethodInvocation) {
- // DefiniteNullToNonNullParameter || PotentialNullToNonNullParameter
- MethodInvocation methodInvocation= (MethodInvocation) selectedNode.getParent();
- int paramIdx= methodInvocation.arguments().indexOf(selectedNode);
- IMethodBinding methodBinding= methodInvocation.resolveMethodBinding();
- compilationUnit= findCUForMethod(compilationUnit, cu, methodBinding);
- if (compilationUnit == null)
- return null;
- if (thisUnitOnly && !compilationUnit.getJavaElement().equals(cu))
- return null;
- ASTNode methodDecl= compilationUnit.findDeclaringNode(methodBinding.getKey());
- if (methodDecl == null)
- return null;
- String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_method_parameter_nullness, annotationNameLabel);
- return new ParameterAnnotationRewriteOperation(compilationUnit, (MethodDeclaration) methodDecl, annotationToAdd, annotationToRemove, paramIdx, allowRemove, message);
+ if (changeTargetMethod) {
+ MethodInvocation methodInvocation= null;
+ if (isArgumentProblem) {
+ if (selectedNode.getParent() instanceof MethodInvocation)
+ methodInvocation= (MethodInvocation) selectedNode.getParent();
+ } else {
+ if (selectedNode instanceof MethodInvocation)
+ methodInvocation= (MethodInvocation) selectedNode;
+ }
+ if (methodInvocation != null) {
+ // DefiniteNullToNonNullParameter || PotentialNullToNonNullParameter
+ int paramIdx= methodInvocation.arguments().indexOf(selectedNode);
+ IMethodBinding methodBinding= methodInvocation.resolveMethodBinding();
+ compilationUnit= findCUForMethod(compilationUnit, cu, methodBinding);
+ if (compilationUnit == null)
+ return null;
+ if (thisUnitOnly && !compilationUnit.getJavaElement().equals(cu))
+ return null;
+ ASTNode methodDecl= compilationUnit.findDeclaringNode(methodBinding.getKey());
+ if (methodDecl == null)
+ return null;
+ if (isArgumentProblem) {
+ String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_target_method_parameter_nullness,
+ new Object[] {methodInvocation.getName(), annotationNameLabel});
+ return new ParameterAnnotationRewriteOperation(compilationUnit, (MethodDeclaration) methodDecl, annotationToAdd, annotationToRemove, paramIdx, allowRemove, message);
+ } else {
+ MethodDeclaration declaration = (MethodDeclaration) methodDecl;
+ String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_method_return_nullness,
+ new String[] { declaration.getName().getIdentifier(), annotationNameLabel });
+ return new ReturnAnnotationRewriteOperation(compilationUnit, declaration, annotationToAdd, annotationToRemove, allowRemove, message);
+ }
+ }
} else if (declaringNode instanceof MethodDeclaration) {
// complaint is in signature of this method
MethodDeclaration declaration= (MethodDeclaration) declaringNode;
@@ -307,13 +372,14 @@ public class NullAnnotationsRewriteOperations {
case IProblem.ParameterLackingNullableAnnotation:
case IProblem.IllegalDefinitionToNonNullParameter:
case IProblem.IllegalRedefinitionToNonNullParameter:
- case IProblem.NonNullLocalVariableComparisonYieldsFalse:
- case IProblem.RedundantNullCheckOnNonNullLocalVariable:
- // statements suggest changing parameters:
+ case IProblem.SpecdNonNullLocalVariableComparisonYieldsFalse:
+ case IProblem.RedundantNullCheckOnSpecdNonNullLocalVariable:
+ // problems regarding the argument declaration:
if (declaration.getNodeType() == ASTNode.METHOD_DECLARATION) {
String paramName= findAffectedParameterName(selectedNode);
if (paramName != null) {
- String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_method_parameter_nullness, annotationNameLabel);
+ String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_method_parameter_nullness,
+ new Object[] {paramName, annotationNameLabel});
return new ParameterAnnotationRewriteOperation(compilationUnit, declaration, annotationToAdd, annotationToRemove, paramName, allowRemove, message);
}
}
@@ -322,13 +388,16 @@ public class NullAnnotationsRewriteOperations {
case IProblem.RequiredNonNullButProvidedPotentialNull:
case IProblem.RequiredNonNullButProvidedSpecdNullable:
case IProblem.RequiredNonNullButProvidedUnknown:
- if (NullAnnotationsFix.isComplainingAboutArgument(selectedNode)) {
- //TODO: duplication
- // statements suggest changing parameters:
- if (declaration.getNodeType() == ASTNode.METHOD_DECLARATION) {
- String paramName= findAffectedParameterName(selectedNode);
+ case IProblem.ConflictingNullAnnotations:
+ case IProblem.ConflictingInheritedNullAnnotations:
+ if (isArgumentProblem) {
+ // statement suggests changing parameters:
+ if (declaration.getNodeType() == ASTNode.METHOD_DECLARATION && selectedNode instanceof SimpleName) {
+ // don't call findAffectedParameterName(), in this branch we're not interested in any target method
+ String paramName= ((SimpleName) selectedNode).getIdentifier();
if (paramName != null) {
- String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_method_parameter_nullness, annotationNameLabel);
+ String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_method_parameter_nullness,
+ new Object[] { paramName, annotationNameLabel });
return new ParameterAnnotationRewriteOperation(compilationUnit, declaration, annotationToAdd, annotationToRemove, paramName, allowRemove, message);
}
}
@@ -344,7 +413,7 @@ public class NullAnnotationsRewriteOperations {
}
private static SignatureAnnotationRewriteOperation createAddAnnotationToOverriddenOperation(CompilationUnit compilationUnit, IProblemLocation problem, String annotationToAdd,
- String annotationToRemove, Set<String> handledPositions, boolean thisUnitOnly, boolean allowRemove) {
+ String annotationToRemove, boolean allowRemove) {
ICompilationUnit cu= (ICompilationUnit) compilationUnit.getJavaElement();
if (!JavaModelUtil.is50OrHigher(cu.getJavaProject()))
return null;

Back to the top