Fixed bug 478136: [1.8][clean up] Lambda rewriter removes annotations
from method

Change-Id: I6c0b4bf1cb4f625ee65ff1c8cba3707f33ace7e6
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest18.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest18.java
index 79dc1f4..350713e 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest18.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AssistQuickFixTest18.java
@@ -36,6 +36,7 @@
 
 import org.eclipse.jdt.ui.PreferenceConstants;
 import org.eclipse.jdt.ui.tests.core.Java18ProjectTestSetup;
+import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
 
 import org.eclipse.jdt.internal.ui.JavaPlugin;
 import org.eclipse.jdt.internal.ui.text.correction.AssistContext;
@@ -943,6 +944,74 @@
 		assertExpectedExistInProposals(proposals, new String[] { expected1 });
 	}
 
+	public void testConvertToLambda19() throws Exception {
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test", false, null);
+		StringBuffer buf= new StringBuffer();
+		buf.append("package test;\n");
+		buf.append("public class C1 {\n");
+		buf.append("    Runnable r1 = new/*[1]*/ Runnable() {\n");
+		buf.append("        @Override @A @Deprecated\n");
+		buf.append("        public void run() {\n");
+		buf.append("        }\n");
+		buf.append("    };\n");
+		buf.append("    Runnable r2 = new/*[2]*/ Runnable() {\n");
+		buf.append("        @Override @Deprecated\n");
+		buf.append("        public void run() {\n");
+		buf.append("        }\n");
+		buf.append("    };\n");
+		buf.append("}\n");
+		buf.append("@interface A {}\n");
+		ICompilationUnit cu= pack1.createCompilationUnit("C1.java", buf.toString(), false, null);
+
+		int offset= buf.toString().indexOf("new/*[1]*/");
+		AssistContext context= getCorrectionContext(cu, offset, 0);
+		assertNoErrors(context);
+		List<IJavaCompletionProposal> proposals= collectAssists(context, false);
+
+		assertNumberOfProposals(proposals, 1);
+		assertCorrectLabels(proposals);
+
+		StringBuffer buf1= new StringBuffer();
+		buf1.append("package test;\n");
+		buf1.append("public class C1 {\n");
+		buf1.append("    Runnable r1 = () -> {\n");
+		buf1.append("    };\n");
+		buf1.append("    Runnable r2 = new/*[2]*/ Runnable() {\n");
+		buf1.append("        @Override @Deprecated\n");
+		buf1.append("        public void run() {\n");
+		buf1.append("        }\n");
+		buf1.append("    };\n");
+		buf1.append("}\n");
+		buf1.append("@interface A {}\n");
+		String expected= buf1.toString();
+
+		assertExpectedExistInProposals(proposals, new String[] { expected });
+
+		offset= buf.toString().indexOf("new/*[2]*/");
+		context= getCorrectionContext(cu, offset, 0);
+		assertNoErrors(context);
+		proposals= collectAssists(context, false);
+
+		assertNumberOfProposals(proposals, 1);
+		assertCorrectLabels(proposals);
+
+		buf1= new StringBuffer();
+		buf1.append("package test;\n");
+		buf1.append("public class C1 {\n");
+		buf1.append("    Runnable r1 = new/*[1]*/ Runnable() {\n");
+		buf1.append("        @Override @A @Deprecated\n");
+		buf1.append("        public void run() {\n");
+		buf1.append("        }\n");
+		buf1.append("    };\n");
+		buf1.append("    Runnable r2 = () -> {\n");
+		buf1.append("    };\n");
+		buf1.append("}\n");
+		buf1.append("@interface A {}\n");
+		expected= buf1.toString();
+
+		assertExpectedExistInProposals(proposals, new String[] { expected });
+	}
+
 	public void testConvertToLambdaAmbiguousOverridden() throws Exception {
 		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
 		StringBuffer buf= new StringBuffer();
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/CleanUpTest18.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/CleanUpTest18.java
index 46b67a3..825cc94 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/CleanUpTest18.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/CleanUpTest18.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2014 IBM Corporation and others.
+ * Copyright (c) 2013, 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
@@ -702,6 +702,46 @@
 		assertRefactoringResultAsExpected(new ICompilationUnit[] { cu1 }, new String[] { expected1 });
 	}
 
+	public void testConvertToLambdaWithMethodAnnotations() throws Exception {
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test", false, null);
+		StringBuffer buf= new StringBuffer();
+		buf.append("package test;\n");
+		buf.append("public class C1 {\n");
+		buf.append("    Runnable r1 = new Runnable() {\n");
+		buf.append("        @Override @A @Deprecated\n");
+		buf.append("        public void run() {\n");
+		buf.append("        }\n");
+		buf.append("    };\n");
+		buf.append("    Runnable r2 = new Runnable() {\n");
+		buf.append("        @Override @Deprecated\n");
+		buf.append("        public void run() {\n");
+		buf.append("        }\n");
+		buf.append("    };\n");
+		buf.append("}\n");
+		buf.append("@interface A {}\n");
+		String original= buf.toString();
+		ICompilationUnit cu1= pack1.createCompilationUnit("C1.java", original, false, null);
+
+		enable(CleanUpConstants.CONVERT_FUNCTIONAL_INTERFACES);
+		enable(CleanUpConstants.USE_LAMBDA);
+
+		buf= new StringBuffer();
+		buf.append("package test;\n");
+		buf.append("public class C1 {\n");
+		buf.append("    Runnable r1 = new Runnable() {\n");
+		buf.append("        @Override @A @Deprecated\n");
+		buf.append("        public void run() {\n");
+		buf.append("        }\n");
+		buf.append("    };\n");
+		buf.append("    Runnable r2 = () -> {\n");
+		buf.append("    };\n");
+		buf.append("}\n");
+		buf.append("@interface A {}\n");
+		String expected1= buf.toString();
+
+		assertRefactoringResultAsExpected(new ICompilationUnit[] { cu1 }, new String[] { expected1 });
+	}
+
 	public void testConvertToAnonymousWithWildcards() throws Exception {
 		IPackageFragment pack1= fSourceFolder.createPackageFragment("test", false, null);
 		StringBuffer buf= new StringBuffer();
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/LambdaExpressionsFix.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/LambdaExpressionsFix.java
index 2c7eb88..ee88eff 100644
--- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/LambdaExpressionsFix.java
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/LambdaExpressionsFix.java
@@ -36,6 +36,7 @@
 import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jdt.core.dom.Expression;
 import org.eclipse.jdt.core.dom.ExpressionStatement;
+import org.eclipse.jdt.core.dom.IAnnotationBinding;
 import org.eclipse.jdt.core.dom.IBinding;
 import org.eclipse.jdt.core.dom.IMethodBinding;
 import org.eclipse.jdt.core.dom.ITypeBinding;
@@ -89,7 +90,7 @@
 		
 		@Override
 		public boolean visit(ClassInstanceCreation node) {
-			if (isFunctionalAnonymous(node)) {
+			if (isFunctionalAnonymous(node) && !fConversionRemovesAnnotations) {
 				fNodes.add(node);
 			}
 			return true;
@@ -519,6 +520,8 @@
 		}
 	}
 
+	private static boolean fConversionRemovesAnnotations;
+
 	public static LambdaExpressionsFix createConvertToLambdaFix(ClassInstanceCreation cic) {
 		CompilationUnit root= (CompilationUnit) cic.getRoot();
 		if (!JavaModelUtil.is18OrHigher(root.getJavaElement().getJavaProject()))
@@ -609,10 +612,28 @@
 		
 		if (!isInTargetTypeContext(node))
 			return false;
-		
+
+		// Check if annotations other than @Override and @Deprecated will be removed
+		checkAnnotationsRemoval(methodBinding);
+
 		return true;
 	}
 
+	private static void checkAnnotationsRemoval(IMethodBinding methodBinding) {
+		fConversionRemovesAnnotations= false;
+		IAnnotationBinding[] declarationAnnotations= methodBinding.getAnnotations();
+		for (IAnnotationBinding declarationAnnotation : declarationAnnotations) {
+			ITypeBinding annotationType= declarationAnnotation.getAnnotationType();
+			if (annotationType != null) {
+				String qualifiedName= annotationType.getQualifiedName();
+				if (!"java.lang.Override".equals(qualifiedName) && !"java.lang.Deprecated".equals(qualifiedName)) { //$NON-NLS-1$ //$NON-NLS-2$
+					fConversionRemovesAnnotations= true;
+					return;
+				}
+			}
+		}
+	}
+
 	private static boolean isInTargetTypeContext(ClassInstanceCreation node) {
 		ITypeBinding targetType= ASTNodes.getTargetType(node);
 		return targetType != null && targetType.getFunctionalInterfaceMethod() != null;