/*******************************************************************************
 * Copyright (c) 2011, 2018 GK Software AG and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Stephan Herrmann <stephan@cs.tu-berlin.de> - [quick fix] Add quick fixes for null annotations - https://bugs.eclipse.org/337977
 *     IBM Corporation - bug fixes
 *******************************************************************************/
package org.eclipse.jdt.internal.corext.fix;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;

import org.eclipse.text.edits.TextEditGroup;

import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMemberValuePair;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
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.ArrayType;
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Dimension;
import org.eclipse.jdt.core.dom.FieldDeclaration;
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.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.LambdaExpression;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.VariableDeclaration;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.TypeLocation;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;

import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.corext.codemanipulation.RedundantNullnessTypeAnnotationsFilter;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFix.CompilationUnitRewriteOperation;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.ui.text.java.IProblemLocation;

import org.eclipse.jdt.internal.ui.JavaPlugin;

public class NullAnnotationsRewriteOperations {

	static final String TYPE_USE_NAME= ElementType.class.getName()+'.'+ElementType.TYPE_USE.name();

	// reduced copy of org.eclipse.jdt.annotation.DefaultLocation:
	enum DefaultLocation {
		PARAMETER,
		RETURN_TYPE
	}

	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 {
		// initialized from the Builder:
		protected CompilationUnit fUnit;
		protected String fAnnotationToAdd;
		protected String fAnnotationToRemove;
		protected boolean fAllowRemove;
		protected boolean fUseNullTypeAnnotations;
		protected boolean fRequireExplicitAnnotation;
		// assigned within constructors:
		protected String fKey;
		protected String fMessage;
		// assigned after the constructor:
		boolean fRemoveIfNonNullByDefault;
		Set<String> fNonNullByDefaultNames;

		protected SignatureAnnotationRewriteOperation(Builder builder) {
			fUnit= builder.fUnit;
			fAnnotationToAdd= builder.fAnnotationToAdd;
			fAnnotationToRemove= builder.fAnnotationToRemove;
			fAllowRemove= builder.fAllowRemove;
			fUseNullTypeAnnotations= builder.fUseNullTypeAnnotations;
			fRequireExplicitAnnotation= builder.requiresExplicitAnnotation();
		}

		/* A globally unique key that identifies the position being annotated (for avoiding double annotations). */
		public String getKey() {
			return fKey;
		}

		public CompilationUnit getCompilationUnit() {
			return fUnit;
		}

		protected ListRewrite getAnnotationListRewrite(Type type, CompilationUnitRewrite cuRewrite, ASTNode declaration, ChildListPropertyDescriptor declAnnotationsProperty) {
			if (fUseNullTypeAnnotations) {
				if (type.isArrayType()) {
					List<Dimension> dimensions= ((ArrayType) type).dimensions();
					if (!dimensions.isEmpty()) {
						Dimension outerDim= dimensions.get(0);
						return cuRewrite.getASTRewrite().getListRewrite(outerDim, Dimension.ANNOTATIONS_PROPERTY);
					}
				}
				// note that in DOM parameter/return annotations are never on the type, always on the declaration
			}
			return cuRewrite.getASTRewrite().getListRewrite(declaration, declAnnotationsProperty);
		}

		boolean checkExisting(ListRewrite listRewrite, TextEditGroup editGroup) {
			List<IExtendedModifier> existingModifiers= listRewrite.getOriginalList();
			for (Object mod : existingModifiers) {
				if (mod instanceof MarkerAnnotation) {
					MarkerAnnotation annotation= (MarkerAnnotation) mod;
					String existingName= annotation.getTypeName().getFullyQualifiedName();
					int lastDot= fAnnotationToRemove.lastIndexOf('.');
					if (existingName.equals(fAnnotationToRemove) || (lastDot != -1 && fAnnotationToRemove.substring(lastDot + 1).equals(existingName))) {
						if (!fAllowRemove)
							return false; // veto this change
						listRewrite.remove(annotation, editGroup);
						return true;
					}
					// paranoia: check if by accident the annotation is already present (shouldn't happen):
					lastDot= fAnnotationToAdd.lastIndexOf('.');
					if (existingName.equals(fAnnotationToAdd) || (lastDot != -1 && fAnnotationToAdd.substring(lastDot + 1).equals(existingName))) {
						return false; // already present
					}
				}
			}
			return true;
		}

		boolean hasNonNullDefault(ASTNode astNode, IBinding enclosingElement, int parameterRank, DefaultLocation defaultLocation) {
			if (!fRemoveIfNonNullByDefault || fNonNullByDefaultNames == null)
				return false;
			ITypeBinding affectedType= null;
			if (enclosingElement instanceof IMethodBinding) {
				switch (defaultLocation) {
					case RETURN_TYPE:
						affectedType= ((IMethodBinding) enclosingElement).getReturnType();
						break;
					case PARAMETER:
						affectedType= ((IMethodBinding) enclosingElement).getParameterTypes()[parameterRank];
						break;
					default:
						// no other locations supported yet (fields?)
				}
			} else if (enclosingElement instanceof IVariableBinding) {
				affectedType= ((IVariableBinding) enclosingElement).getType();
			}
			if (affectedType != null) {
				if (affectedType.isTypeVariable() || affectedType.isWildcardType()) {
					return false; // not affected by @NonNullByDefault
				}
			}
			EnumSet<TypeLocation> nonNullByDefaultLocations= RedundantNullnessTypeAnnotationsFilter.determineNonNullByDefaultLocations(astNode,
					fNonNullByDefaultNames);
			switch (defaultLocation) {
				case PARAMETER:
					return nonNullByDefaultLocations.contains(TypeLocation.PARAMETER);
				case RETURN_TYPE:
					return nonNullByDefaultLocations.contains(TypeLocation.RETURN_TYPE);
			}
			return false;
		}

		public String getMessage() {
			return fMessage;
		}
	}

	/**
	 * Rewrite operation that inserts an annotation into a method signature.
	 *
	 * Crafted after the lead of Java50Fix.AnnotationRewriteOperation
	 */
	static class ReturnAnnotationRewriteOperation extends SignatureAnnotationRewriteOperation {

		private final MethodDeclaration fBodyDeclaration;

		ReturnAnnotationRewriteOperation(MethodDeclaration method, String message, Builder builder) {
			super(builder);
			fKey= method.resolveBinding().getKey() + "<return>"; //$NON-NLS-1$
			fBodyDeclaration= method;
			fMessage= message;
		}

		@Override
		public void rewriteAST(CompilationUnitRewrite cuRewrite, LinkedProposalModel model) throws CoreException {
			AST ast= cuRewrite.getRoot().getAST();
			ListRewrite listRewrite= getAnnotationListRewrite(fBodyDeclaration.getReturnType2(), cuRewrite,
										fBodyDeclaration, fBodyDeclaration.getModifiersProperty());
			TextEditGroup group= createTextEditGroup(fMessage, cuRewrite);
			if (!checkExisting(listRewrite, group))
				return;
			if (!fRequireExplicitAnnotation) {
				if (hasNonNullDefault(fBodyDeclaration, fBodyDeclaration.resolveBinding(), /*parameterRank*/-1, DefaultLocation.RETURN_TYPE))
					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);
			newAnnotation.setTypeName(ast.newName(resolvableName));
			listRewrite.insertLast(newAnnotation, group); // null annotation is last modifier, directly preceding the return type
		}
	}

	static class ParameterAnnotationRewriteOperation extends SignatureAnnotationRewriteOperation {

		static class IndexedParameter {
			int index;
			String name;
			IndexedParameter(int index, String name) {
				this.index= index;
				this.name= name;
			}
		}

		private SingleVariableDeclaration fArgument;
		private int fParameterRank;

		// for lambda parameter (can return null):
		static ParameterAnnotationRewriteOperation create(LambdaExpression lambda, IndexedParameter parameter, String message, Builder builder) {
			IMethodBinding lambdaMethodBinding= lambda.resolveMethodBinding();
			List<?> parameters= lambda.parameters();
			if (parameters.size() > parameter.index) {
				Object param= parameters.get(parameter.index);
				if (!(param instanceof SingleVariableDeclaration)) {
					return null; // type elided lambda
				}
				return new ParameterAnnotationRewriteOperation(lambdaMethodBinding, parameters, parameter.index, message, builder);
			}
			// shouldn't happen, we've checked that paramName indeed denotes a parameter.
			throw new RuntimeException("Argument " + parameter.name + " not found in method " + lambda.toString()); //$NON-NLS-1$ //$NON-NLS-2$
		}

		// for method parameter:
		ParameterAnnotationRewriteOperation(MethodDeclaration method, int paramIdx, String message, Builder builder) {
			this(method.resolveBinding(), method.parameters(), paramIdx, message, builder);
		}

		private ParameterAnnotationRewriteOperation(IMethodBinding methodBinding, List<?> parameters, int paramIdx, String message, Builder builder) {
			super(builder);
			fKey= methodBinding.getKey();
			fArgument= (SingleVariableDeclaration) parameters.get(paramIdx);
			fParameterRank= paramIdx;
			fKey+= fArgument.getName().getIdentifier();
			fMessage= message;
		}

		@Override
		public void rewriteAST(CompilationUnitRewrite cuRewrite, LinkedProposalModel linkedModel) throws CoreException {
			AST ast= cuRewrite.getRoot().getAST();
			ListRewrite listRewrite= getAnnotationListRewrite(fArgument.getType(), cuRewrite, fArgument, SingleVariableDeclaration.MODIFIERS2_PROPERTY);
			TextEditGroup group= createTextEditGroup(fMessage, cuRewrite);
			if (!checkExisting(listRewrite, group))
				return;
			if (!fRequireExplicitAnnotation) {
				if (hasNonNullDefault(fArgument, fArgument.resolveBinding(), fParameterRank, DefaultLocation.PARAMETER))
					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);
			newAnnotation.setTypeName(ast.newName(resolvableName));
			listRewrite.insertLast(newAnnotation, group); // null annotation is last modifier, directly preceding the type
		}
	}

	static class RemoveRedundantAnnotationRewriteOperation extends CompilationUnitRewriteOperation {

		private IProblemLocation fProblem;
		private CompilationUnit fCompilationUnit;

		public RemoveRedundantAnnotationRewriteOperation(CompilationUnit compilationUnit, IProblemLocation problem) {
			fCompilationUnit= compilationUnit;
			fProblem= problem;
		}

		@Override
		public void rewriteAST(CompilationUnitRewrite cuRewrite, LinkedProposalModel linkedModel) throws CoreException {
			TextEditGroup group= createTextEditGroup(FixMessages.NullAnnotationsRewriteOperations_remove_redundant_nullness_annotation, cuRewrite);
			ASTRewrite astRewrite= cuRewrite.getASTRewrite();

			CompilationUnit astRoot= fCompilationUnit;
			ASTNode selectedNode= fProblem.getCoveringNode(astRoot);

			if (fProblem.getProblemId() == IProblem.RedundantNullAnnotation) {
				List<IExtendedModifier> modifiers;
				if (selectedNode instanceof SingleVariableDeclaration) {
					SingleVariableDeclaration singleVariableDeclaration= (SingleVariableDeclaration) selectedNode;
					modifiers= singleVariableDeclaration.modifiers();
				} else if (selectedNode instanceof FieldDeclaration) {
					FieldDeclaration fieldDeclaration= (FieldDeclaration) selectedNode;
					modifiers= fieldDeclaration.modifiers();
				} else if (selectedNode instanceof MethodDeclaration) {
					MethodDeclaration methodDeclaration= (MethodDeclaration) selectedNode;
					modifiers= methodDeclaration.modifiers();
				} else {
					return;
				}

				for (IExtendedModifier modifier : modifiers) {
					if (modifier instanceof MarkerAnnotation) {
						MarkerAnnotation annotation= (MarkerAnnotation) modifier;
						IAnnotationBinding annotationBinding= annotation.resolveAnnotationBinding();
						String name= annotationBinding.getName();
						if (name.equals(NullAnnotationsFix.getNonNullAnnotationName(fCompilationUnit.getJavaElement(), true))) {
							astRewrite.remove(annotation, group);
						}
					}
				}
			} else {
				if (!(selectedNode instanceof Annotation))
					return;
				Annotation annotation= (Annotation) selectedNode;
				IAnnotationBinding annotationBinding= annotation.resolveAnnotationBinding();
				String name= annotationBinding.getName();
				if (name.equals(NullAnnotationsFix.getNonNullByDefaultAnnotationName(fCompilationUnit.getJavaElement(), true))) {
					astRewrite.remove(annotation, group);
				}
			}
		}
	}

	static class AddMissingDefaultNullnessRewriteOperation extends CompilationUnitRewriteOperation {

		private IProblemLocation fProblem;
		private CompilationUnit fCompilationUnit;

		public AddMissingDefaultNullnessRewriteOperation(CompilationUnit compilationUnit, IProblemLocation problem) {
			fCompilationUnit= compilationUnit;
			fProblem= problem;
		}

		@Override
		public void rewriteAST(CompilationUnitRewrite cuRewrite, LinkedProposalModel linkedModel) throws CoreException {

			if (fProblem.getProblemId() == IProblem.MissingNonNullByDefaultAnnotationOnPackage) {
				PackageDeclaration packageDeclaration= fCompilationUnit.getPackage();
				if (packageDeclaration != null) {
					String nonNullByDefaultAnnotationname= NullAnnotationsFix.getNonNullByDefaultAnnotationName(fCompilationUnit.getJavaElement(), true);
					String label= Messages.format(FixMessages.NullAnnotationsRewriteOperations_add_missing_default_nullness_annotation, new String[] { nonNullByDefaultAnnotationname });
					TextEditGroup group= createTextEditGroup(label, cuRewrite);
					ASTRewrite astRewrite= cuRewrite.getASTRewrite();
					AST ast= cuRewrite.getRoot().getAST();
					ListRewrite listRewrite= astRewrite.getListRewrite(packageDeclaration, PackageDeclaration.ANNOTATIONS_PROPERTY);
					Annotation newAnnotation= ast.newMarkerAnnotation();
					// NOTE: to be consistent with completion proposals, don't use import in package-info.java
					String annotationToAdd= NullAnnotationsFix.getNonNullByDefaultAnnotationName(fCompilationUnit.getJavaElement(), false);
					newAnnotation.setTypeName(ast.newName(annotationToAdd));
					listRewrite.insertLast(newAnnotation, group);
					return;
				}
			}
		}
	}

	public static class Builder {

		IProblemLocation fProblem;
		ChangeKind fChangeKind;
		CompilationUnit fUnit;
		String fAnnotationToAdd;
		String fAnnotationToRemove;
		boolean fAllowRemove;
		boolean fAffectsParameter;
		boolean fUseNullTypeAnnotations;

		public Builder(IProblemLocation problem, CompilationUnit unit, String annotationToAdd, String annotationToRemove,
				boolean allowRemove, boolean affectsParameter, ChangeKind changeKind)
		{
			fChangeKind= changeKind;
			fUnit= unit;
			fAnnotationToAdd= annotationToAdd;
			fAnnotationToRemove= annotationToRemove;
			fAllowRemove= allowRemove;
			fAffectsParameter= affectsParameter;
			fProblem= problem;
			fUseNullTypeAnnotations= usesNullTypeAnnotations(unit.getJavaElement(), annotationToAdd);
		}

		private boolean usesNullTypeAnnotations(IJavaElement cu, String annotationName) {
			IJavaProject project= (IJavaProject) cu.getAncestor(IJavaElement.JAVA_PROJECT);
			if (!JavaModelUtil.is1d8OrHigher(project)) {
				return false;
			}
			try {
				IType annotationType= project.findType(annotationName);
				if (annotationType == null) {
					return false;
				}
				for (IAnnotation annotation : annotationType.getAnnotations()) {
					if (annotationType.isBinary()) {
						if (annotation.getElementName().equals(Target.class.getName())) {
							for (IMemberValuePair valuePair : annotation.getMemberValuePairs()) {
								if (TYPE_USE_NAME.equals(valuePair.getValue())) {
									return true;
								}
							}
							return false;
						}
					} else {
						String[][] resolveType= annotationType.resolveType(annotation.getElementName());
						if (resolveType != null && resolveType.length == 1 && (resolveType[0][0].equals(Target.class.getPackage().getName())
							&& resolveType[0][1].equals(Target.class.getSimpleName()))) {
							for (IMemberValuePair valuePair : annotation.getMemberValuePairs()) {
								final Object value= valuePair.getValue();
								if (value instanceof String) {
									if (((String) value).endsWith(ElementType.TYPE_USE.name())) {
										return true;
									}
								} else if (value instanceof Object[]) {
									for (Object v : (Object[]) value) {
										if (v instanceof String) {
											if (((String) v).endsWith(ElementType.TYPE_USE.name())) {
												return true;
											}
										}
									}
								}
							}
							return false;
						}
					}
				}
			} catch (JavaModelException e) {
				JavaPlugin.log(e);
			}
			return false;
		}

		public boolean requiresExplicitAnnotation() {
			switch (fProblem.getProblemId()) {
				case IProblem.ConflictingInheritedNullAnnotations:
				case IProblem.ConflictingNullAnnotations:
					return fChangeKind != ChangeKind.OVERRIDDEN;
				default:
					return false;
			}
		}

		public void swapAnnotations() {
			String tmp= fAnnotationToAdd;
			fAnnotationToAdd= fAnnotationToRemove;
			fAnnotationToRemove= tmp;
		}

		public boolean is50OrHigher() {
			CompilationUnit compilationUnit= fUnit;
			ICompilationUnit cu= (ICompilationUnit) compilationUnit.getJavaElement();
			return JavaModelUtil.is50OrHigher(cu.getJavaProject());
		}

		public ASTNode getCoveringNode() {
			return fProblem.getCoveringNode(fUnit);
		}

		// Entry for QuickFixes:
		public SignatureAnnotationRewriteOperation createAddAnnotationOperation(Set<String> handledPositions, boolean thisUnitOnly, ChangeKind changeKind) {
			// precondition:
			// thisUnitOnly => changeKind == LOCAL
			SignatureAnnotationRewriteOperation result;
			if (changeKind == ChangeKind.OVERRIDDEN)
				result= createAddAnnotationToOverriddenOperation();
			else
				result= createAddAnnotationOperation(changeKind == ChangeKind.TARGET, thisUnitOnly);
			if (handledPositions != null && result != null) {
				if (handledPositions.contains(result.getKey()))
					return null;
				handledPositions.add(result.getKey());
			}
			return result;
		}

		private SignatureAnnotationRewriteOperation createAddAnnotationOperation(boolean changeTargetMethod, boolean thisUnitOnly) {
			if (!is50OrHigher())
				return null;

			ASTNode selectedNode= getCoveringNode();
			if (selectedNode == null)
				return null;

			ICompilationUnit cu= (ICompilationUnit) fUnit.getJavaElement();
			ASTNode declaringNode= getDeclaringNode(selectedNode);

			switch (fProblem.getProblemId()) {
				case IProblem.IllegalDefinitionToNonNullParameter:
//			case IllegalRedefinitionToNonNullParameter:
					// these affect another method
					break;
				case IProblem.IllegalReturnNullityRedefinition:
					if (declaringNode == null)
						declaringNode= selectedNode;
					break; // do propose changes even if we already have an annotation
				default:
					// if this method has annotations, don't change'em
					if (!fAllowRemove && NullAnnotationsFix.hasExplicitNullAnnotation(cu, fProblem.getOffset()))
						return null;
			}

			String annotationNameLabel= fAnnotationToAdd;
			int lastDot= annotationNameLabel.lastIndexOf('.');
			if (lastDot != -1)
				annotationNameLabel= annotationNameLabel.substring(lastDot + 1);
			annotationNameLabel= BasicElementLabels.getJavaElementName(annotationNameLabel);

			if (changeTargetMethod) {
				MethodInvocation methodInvocation= null;
				if (fAffectsParameter) {
					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();
					MethodDeclaration methodDecl= findMethodDeclarationInUnit(cu, methodBinding, thisUnitOnly);
					if (methodDecl == null)
						return null;
					if (fAffectsParameter) {
						String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_target_method_parameter_nullness,
								new Object[] {methodInvocation.getName(), annotationNameLabel});
						return new ParameterAnnotationRewriteOperation(methodDecl, paramIdx, message, this);
					} else {
						MethodDeclaration declaration = methodDecl;
						String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_method_return_nullness,
								new String[] { declaration.getName().getIdentifier(), annotationNameLabel });
						return new ReturnAnnotationRewriteOperation(declaration, message, this);
					}
				}
			} else if (declaringNode instanceof MethodDeclaration || declaringNode instanceof LambdaExpression) {
				// complaint is in signature of this method / lambda
				switch (fProblem.getProblemId()) {
					case IProblem.ParameterLackingNonNullAnnotation:
					case IProblem.ParameterLackingNullableAnnotation:
					case IProblem.IllegalDefinitionToNonNullParameter:
					case IProblem.IllegalRedefinitionToNonNullParameter:
						// problems regarding the argument declaration:
						ParameterAnnotationRewriteOperation.IndexedParameter parameter= findParameterDeclaration(selectedNode);
						if (parameter != null) {
							switch (declaringNode.getNodeType()) {
								case ASTNode.METHOD_DECLARATION:
									MethodDeclaration method= (MethodDeclaration) declaringNode;
									String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_method_parameter_nullness,
											new Object[] {parameter.name, annotationNameLabel});
									return new ParameterAnnotationRewriteOperation(method, parameter.index, message, this);
								case ASTNode.LAMBDA_EXPRESSION:
									LambdaExpression lambda = (LambdaExpression) declaringNode;
									// TODO: specific message for lambda
									message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_method_parameter_nullness,
											new Object[] {parameter.name, annotationNameLabel});
									return ParameterAnnotationRewriteOperation.create(lambda, parameter, message, this);
								default:
									return null;
							}
						}
						break;
					case IProblem.SpecdNonNullLocalVariableComparisonYieldsFalse:
					case IProblem.RedundantNullCheckOnSpecdNonNullLocalVariable:
					case IProblem.RequiredNonNullButProvidedNull:
					case IProblem.RequiredNonNullButProvidedPotentialNull:
					case IProblem.RequiredNonNullButProvidedSpecdNullable:
					case IProblem.RequiredNonNullButProvidedUnknown:
					case IProblem.ConflictingNullAnnotations:
					case IProblem.ConflictingInheritedNullAnnotations:
					case IProblem.RedundantNullCheckAgainstNonNullType:
						if (fAffectsParameter) {
							// statement suggests changing parameters:
							if (selectedNode instanceof SimpleName) {
								parameter= findReferencedParameter(selectedNode);
								if (parameter != null) {
									switch (declaringNode.getNodeType()) {
										case ASTNode.METHOD_DECLARATION:
											MethodDeclaration declaration= (MethodDeclaration) declaringNode;
											String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_method_parameter_nullness,
													new Object[] { parameter.name, annotationNameLabel });
											return new ParameterAnnotationRewriteOperation(declaration, parameter.index, message, this);
										case ASTNode.LAMBDA_EXPRESSION:
											LambdaExpression lambda= (LambdaExpression) declaringNode;
											// TODO: appropriate message for lambda
											message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_method_parameter_nullness,
													new Object[] { parameter.name, annotationNameLabel });
											return ParameterAnnotationRewriteOperation.create(lambda, parameter, message, this);
										default:
											return null;
									}
								}
							}
							break;
						}
						//$FALL-THROUGH$
					case IProblem.IllegalReturnNullityRedefinition:
						if (declaringNode.getNodeType()== ASTNode.METHOD_DECLARATION) {
							MethodDeclaration declaration= (MethodDeclaration) declaringNode;
							String name= declaration.getName().getIdentifier();
							String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_method_return_nullness, new String[] { name, annotationNameLabel });
							return new ReturnAnnotationRewriteOperation(declaration, message, this);
						}
						break;
					default:
						return null;
				}
			}
			return null;
		}

		private SignatureAnnotationRewriteOperation createAddAnnotationToOverriddenOperation() {
			if (!is50OrHigher())
				return null;

			ASTNode selectedNode= getCoveringNode();
			if (selectedNode == null)
				return null;

			ICompilationUnit cu= (ICompilationUnit) fUnit.getJavaElement();
			ASTNode declaringNode= getDeclaringNode(selectedNode);
			switch (fProblem.getProblemId()) {
				case IProblem.IllegalDefinitionToNonNullParameter:
				case IProblem.IllegalRedefinitionToNonNullParameter:
					break;
				case IProblem.IllegalReturnNullityRedefinition:
				case IProblem.ConflictingNullAnnotations:
					if (declaringNode == null)
						declaringNode= selectedNode;
					break;
				default:
					return null;
			}

			String annotationNameLabel= fAnnotationToAdd;
			int lastDot= annotationNameLabel.lastIndexOf('.');
			if (lastDot != -1)
				annotationNameLabel= annotationNameLabel.substring(lastDot + 1);
			annotationNameLabel= BasicElementLabels.getJavaElementName(annotationNameLabel);

			if (declaringNode instanceof MethodDeclaration) {
				// complaint is in signature of this method
				MethodDeclaration declaration= (MethodDeclaration) declaringNode;
				switch (fProblem.getProblemId()) {
				case IProblem.IllegalReturnNullityRedefinition:
					if (!hasNullAnnotation(declaration)) {
						return null; // don't adjust super if local has no explicit annotation (?)
					}
					//$FALL-THROUGH$
				case IProblem.IllegalDefinitionToNonNullParameter:
				case IProblem.IllegalRedefinitionToNonNullParameter:
				case IProblem.ConflictingNullAnnotations:
					if (fAffectsParameter) {
						return createChangeOverriddenParameterOperation(cu, declaration, selectedNode, annotationNameLabel);
					} else {
						return createChangeOverriddenReturnOperation(cu, declaration, annotationNameLabel);
					}
				default:
					return null;
				}
			}
			return null;
		}

		private SignatureAnnotationRewriteOperation createChangeOverriddenParameterOperation(ICompilationUnit cu, MethodDeclaration declaration, ASTNode selectedNode,
				String annotationNameLabel) {
			IMethodBinding methodDeclBinding= declaration.resolveBinding();
			if (methodDeclBinding == null)
				return null;

			IMethodBinding overridden= Bindings.findOverriddenMethod(methodDeclBinding, false);
			if (overridden == null)
				return null;
			MethodDeclaration overriddenDeclaration= findMethodDeclarationInUnit(cu, overridden, false);
			if (overriddenDeclaration == null)
				return null;
			String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_overridden_parameter_nullness, new String[] { overridden.getName(), annotationNameLabel });
			ParameterAnnotationRewriteOperation.IndexedParameter parameter= findParameterDeclaration(selectedNode); // parameter.name is determined from the current method, but this name will not be used here
			if (parameter == null)
				return null;
			return new ParameterAnnotationRewriteOperation(overriddenDeclaration, parameter.index, message, this);
		}

		private ParameterAnnotationRewriteOperation.IndexedParameter findParameterDeclaration(ASTNode selectedNode) {
			VariableDeclaration argDecl= (selectedNode instanceof VariableDeclaration) ? (VariableDeclaration) selectedNode : ASTNodes.getParent(selectedNode,
					VariableDeclaration.class);
			if (argDecl != null) {
				StructuralPropertyDescriptor locationInParent= argDecl.getLocationInParent();
				if (!locationInParent.isChildListProperty())
					return null;
				List<?> containingList= (List<?>) argDecl.getParent().getStructuralProperty(locationInParent);
				return new ParameterAnnotationRewriteOperation.IndexedParameter(containingList.indexOf(argDecl), argDecl.getName().getIdentifier());
			}
			return null;
		}

		private ParameterAnnotationRewriteOperation.IndexedParameter findReferencedParameter(ASTNode selectedNode) {
			if (selectedNode.getNodeType() == ASTNode.SIMPLE_NAME) {
				IBinding binding= ((SimpleName) selectedNode).resolveBinding();
				if (binding.getKind() == IBinding.VARIABLE && ((IVariableBinding) binding).isParameter()) {
					ASTNode current= selectedNode.getParent();
					while (current != null) {
						List<?> parameters= null;
						switch (current.getNodeType()) {
							case ASTNode.METHOD_DECLARATION:
								parameters= ((MethodDeclaration) current).parameters();
								break;
							case ASTNode.LAMBDA_EXPRESSION:
								parameters= ((LambdaExpression) current).parameters();
								break;
							default:
								/* continue traversing outwards */
						}
						if (parameters != null) {
							for (int i= 0; i < parameters.size(); i++) {
								VariableDeclaration parameter= (VariableDeclaration) parameters.get(i);
								if (parameter.resolveBinding() == binding)
									return new ParameterAnnotationRewriteOperation.IndexedParameter(i, binding.getName());
							}
						}
						current= current.getParent();
					}
				}
			}
			return null;
		}

		private boolean hasNullAnnotation(MethodDeclaration decl) {
			List<IExtendedModifier> modifiers= decl.modifiers();
			String nonnull= NullAnnotationsFix.getNonNullAnnotationName(decl.resolveBinding().getJavaElement(), false);
			String nullable= NullAnnotationsFix.getNullableAnnotationName(decl.resolveBinding().getJavaElement(), false);
			for (Object mod : modifiers) {
				if (mod instanceof Annotation) {
					Name annotationName= ((Annotation) mod).getTypeName();
					String fullyQualifiedName= annotationName.getFullyQualifiedName();
					if (annotationName.isSimpleName() ? nonnull.endsWith(fullyQualifiedName) : fullyQualifiedName.equals(nonnull))
						return true;
					if (annotationName.isSimpleName() ? nullable.endsWith(fullyQualifiedName) : fullyQualifiedName.equals(nullable))
						return true;
				}
			}
			return false;
		}

		private SignatureAnnotationRewriteOperation createChangeOverriddenReturnOperation(ICompilationUnit cu, MethodDeclaration declaration, String annotationNameLabel) {
			IMethodBinding methodDeclBinding= declaration.resolveBinding();
			if (methodDeclBinding == null)
				return null;

			IMethodBinding overridden= Bindings.findOverriddenMethod(methodDeclBinding, false);
			if (overridden == null)
				return null;
			declaration= findMethodDeclarationInUnit(cu, overridden, false);
			if (declaration == null)
				return null;
// TODO(SH): decide whether we want to propose overwriting existing annotations in super
//		if (hasNullAnnotation(declaration)) // if overridden has explicit declaration don't propose to change it
//			return null;
			String message= Messages.format(FixMessages.NullAnnotationsRewriteOperations_change_overridden_return_nullness, new String[] { overridden.getName(), annotationNameLabel });
			return new ReturnAnnotationRewriteOperation(declaration, message, this);
		}

		private MethodDeclaration findMethodDeclarationInUnit(ICompilationUnit cu, IMethodBinding method, boolean sameUnitOnly) {
			method= method.getMethodDeclaration();
			CompilationUnit compilationUnit= findCUForMethod(fUnit, cu, method);
			if (compilationUnit == null)
				return null;
			if (sameUnitOnly && !compilationUnit.getJavaElement().equals(cu))
				return null;
			ASTNode methodDecl= compilationUnit.findDeclaringNode(method.getKey());
			if (methodDecl == null)
				return null;
			fUnit= compilationUnit;
			return (MethodDeclaration) methodDecl;
		}

		private CompilationUnit findCUForMethod(CompilationUnit compilationUnit, ICompilationUnit cu, IMethodBinding methodBinding) {
			ASTNode methodDecl= compilationUnit.findDeclaringNode(methodBinding.getMethodDeclaration());
			if (methodDecl == null) {
				// is methodDecl defined in another CU?
				ITypeBinding declaringTypeDecl= methodBinding.getDeclaringClass().getTypeDeclaration();
				if (declaringTypeDecl.isFromSource()) {
					ICompilationUnit targetCU= null;
					try {
						targetCU= ASTResolving.findCompilationUnitForBinding(cu, compilationUnit, declaringTypeDecl);
					} catch (JavaModelException e) { /* can't do better */
					}
					if (targetCU != null) {
						return ASTResolving.createQuickFixAST(targetCU, null);
					}
				}
				return null;
			}
			return compilationUnit;
		}

		/* The relevant declaring node of a return statement is the enclosing method or lambda. */
		private static ASTNode getDeclaringNode(ASTNode selectedNode) {
			while (selectedNode != null) {
				switch (selectedNode.getNodeType()) {
					case ASTNode.METHOD_DECLARATION:
					case ASTNode.LAMBDA_EXPRESSION:
						return selectedNode;
					default:
						selectedNode= selectedNode.getParent();
				}
			}
			return null;
		}
	}

	private NullAnnotationsRewriteOperations() {
	}
}
