Merge remote-tracking branch 'origin/master' into BETA_JAVA9
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull1/in/NoRedundantNonNull1.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull1/in/NoRedundantNonNull1.java
new file mode 100644
index 0000000..36a9cce
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull1/in/NoRedundantNonNull1.java
@@ -0,0 +1,22 @@
+package p;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+@NonNullByDefault({ PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT, ARRAY_CONTENTS })
+class NoRedundantNonNull1 {
+	String string = "A";
+	Integer integer = 2;
+	Map<String, ? extends Number> map = new HashMap<>();
+	Object[][] array = { {}, {} };
+
+	NoRedundantNonNull1(String s1, Integer h1, Map<String, ? extends Number> map1, Object[][] array1) {
+		string = s1;
+		integer = h1;
+		map = map1;
+		array = array1;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull1/out/NoRedundantNonNull1.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull1/out/NoRedundantNonNull1.java
new file mode 100644
index 0000000..04efd89
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull1/out/NoRedundantNonNull1.java
@@ -0,0 +1,20 @@
+package p;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+@NonNullByDefault({ PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT, ARRAY_CONTENTS })
+class NoRedundantNonNull1 {
+	NoRedundantNonNull1Data data = new NoRedundantNonNull1Data("A", 2, new HashMap<>(), new @NonNull Object @NonNull [] @NonNull []{ {}, {} });
+
+	NoRedundantNonNull1(String s1, Integer h1, Map<String, ? extends Number> map1, Object[][] array1) {
+		data.setString(s1);
+		data.setInteger(h1);
+		data.setMap(map1);
+		data.setArray(array1);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull1/out/NoRedundantNonNull1Data.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull1/out/NoRedundantNonNull1Data.java
new file mode 100644
index 0000000..2da793b
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull1/out/NoRedundantNonNull1Data.java
@@ -0,0 +1,42 @@
+package p;
+
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNull;
+
+public class NoRedundantNonNull1Data {
+	private @NonNull String string;
+	private @NonNull Integer integer;
+	private @NonNull Map<@NonNull String, ? extends @NonNull Number> map;
+	private @NonNull Object @NonNull [] @NonNull [] array;
+	public NoRedundantNonNull1Data(@NonNull String string, @NonNull Integer integer, @NonNull Map<@NonNull String, ? extends @NonNull Number> map, @NonNull Object @NonNull [] @NonNull [] array) {
+		this.string = string;
+		this.integer = integer;
+		this.map = map;
+		this.array = array;
+	}
+	public @NonNull String getString() {
+		return string;
+	}
+	public void setString(@NonNull String string) {
+		this.string = string;
+	}
+	public @NonNull Integer getInteger() {
+		return integer;
+	}
+	public void setInteger(@NonNull Integer integer) {
+		this.integer = integer;
+	}
+	public @NonNull Map<@NonNull String, ? extends @NonNull Number> getMap() {
+		return map;
+	}
+	public void setMap(@NonNull Map<@NonNull String, ? extends @NonNull Number> map) {
+		this.map = map;
+	}
+	public @NonNull Object @NonNull [] @NonNull [] getArray() {
+		return array;
+	}
+	public void setArray(@NonNull Object @NonNull [] @NonNull [] array) {
+		this.array = array;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull2/in/NoRedundantNonNull2.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull2/in/NoRedundantNonNull2.java
new file mode 100644
index 0000000..e397bb4
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull2/in/NoRedundantNonNull2.java
@@ -0,0 +1,22 @@
+package p;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+@NonNullByDefault({ PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT, ARRAY_CONTENTS })
+class NoRedundantNonNull2 {
+	String string = "A";
+	Integer integer = 2;
+	Map<String, ? extends Number> map = new HashMap<>();
+	Object[][] array = { {}, {} };
+
+	NoRedundantNonNull2(String s1, Integer h1, Map<String, ? extends Number> map1, Object[][] array1) {
+		string = s1;
+		integer = h1;
+		map = map1;
+		array = array1;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull2/out/NoRedundantNonNull2.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull2/out/NoRedundantNonNull2.java
new file mode 100644
index 0000000..e9b3480
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractClass18/testNoRedundantNonNull2/out/NoRedundantNonNull2.java
@@ -0,0 +1,57 @@
+package p;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+@NonNullByDefault({ PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT, ARRAY_CONTENTS })
+class NoRedundantNonNull2 {
+	public static class NoRedundantNonNull2Data {
+		private String string;
+		private Integer integer;
+		private Map<String, ? extends Number> map;
+		private Object[][] array;
+		public NoRedundantNonNull2Data(String string, Integer integer, Map<String, ? extends Number> map, Object[][] array) {
+			this.string = string;
+			this.integer = integer;
+			this.map = map;
+			this.array = array;
+		}
+		public String getString() {
+			return string;
+		}
+		public void setString(String string) {
+			this.string = string;
+		}
+		public Integer getInteger() {
+			return integer;
+		}
+		public void setInteger(Integer integer) {
+			this.integer = integer;
+		}
+		public Map<String, ? extends Number> getMap() {
+			return map;
+		}
+		public void setMap(Map<String, ? extends Number> map) {
+			this.map = map;
+		}
+		public Object[][] getArray() {
+			return array;
+		}
+		public void setArray(Object[][] array) {
+			this.array = array;
+		}
+	}
+
+	NoRedundantNonNull2Data data = new NoRedundantNonNull2Data("A", 2, new HashMap<>(), new @NonNull Object @NonNull [] @NonNull []{ {}, {} });
+
+	NoRedundantNonNull2(String s1, Integer h1, Map<String, ? extends Number> map1, Object[][] array1) {
+		data.setString(s1);
+		data.setInteger(h1);
+		data.setMap(map1);
+		data.setArray(array1);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_in/A_test990.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_in/A_test990.java
new file mode 100644
index 0000000..dcf95af
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_in/A_test990.java
@@ -0,0 +1,18 @@
+package duplicates_in;
+
+public class A_test990 {
+	public static void main(String[] args) {
+		for (int i = 0; i < 1; i++) {
+			int idx = 0;
+			for (int j = 0; j < 3; j++) {
+				idx++;
+				System.out.println(idx);
+			}
+			// for-loop to extract:
+			/*[*/for (int j = 0; j < 3; j++) {
+				idx++;
+				System.out.println(idx);
+			}/*]*/
+		}
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_in/A_test991.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_in/A_test991.java
new file mode 100644
index 0000000..3248c27
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_in/A_test991.java
@@ -0,0 +1,17 @@
+package duplicates_in;
+
+public class A_test991 {
+	public static void main(String[] args) {
+		for (int i = 0; i < 1; i++) {
+			int idx = 0;
+			/*[*/for (int j = 0; j < 3; j++) {
+				idx++;
+				System.out.println(idx);
+			}/*]*/
+			for (int j = 0; j < 3; j++) {
+				idx++;
+				System.out.println(idx);
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_in/A_test992.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_in/A_test992.java
new file mode 100644
index 0000000..d7c093d
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_in/A_test992.java
@@ -0,0 +1,13 @@
+package duplicates_in;
+
+public class A_test992 {
+	void a() {
+		/*[*/int xxx= 0, yyy= 1;/*]*/
+		System.out.println(xxx);
+	}
+	
+	void b() {
+		int xxx= 0, yyy= 1;
+		System.out.println(yyy);
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_out/A_test990.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_out/A_test990.java
new file mode 100644
index 0000000..0e591f6
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_out/A_test990.java
@@ -0,0 +1,22 @@
+package duplicates_out;

+

+public class A_test990 {

+	public static void main(String[] args) {

+		for (int i = 0; i < 1; i++) {

+			int idx = 0;

+			for (int j = 0; j < 3; j++) {

+				idx++;

+				System.out.println(idx);

+			}

+			// for-loop to extract:

+			extracted(idx);

+		}

+	}

+

+	protected static void extracted(int idx) {

+		/*[*/for (int j = 0; j < 3; j++) {

+			idx++;

+			System.out.println(idx);

+		}/*]*/

+	}

+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_out/A_test991.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_out/A_test991.java
new file mode 100644
index 0000000..5b9f491
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_out/A_test991.java
@@ -0,0 +1,19 @@
+package duplicates_out;

+

+public class A_test991 {

+	public static void main(String[] args) {

+		for (int i = 0; i < 1; i++) {

+			int idx = 0;

+			idx = extracted(idx);

+			idx = extracted(idx);

+		}

+	}

+

+	protected static int extracted(int idx) {

+		/*[*/for (int j = 0; j < 3; j++) {

+			idx++;

+			System.out.println(idx);

+		}/*]*/

+		return idx;

+	}

+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_out/A_test992.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_out/A_test992.java
new file mode 100644
index 0000000..bee4c95
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/duplicates_out/A_test992.java
@@ -0,0 +1,18 @@
+package duplicates_out;

+

+public class A_test992 {

+	void a() {

+		int xxx = extracted();

+		System.out.println(xxx);

+	}

+

+	protected int extracted() {

+		/*[*/int xxx= 0, yyy= 1;/*]*/

+		return xxx;

+	}

+	

+	void b() {

+		int xxx= 0, yyy= 1;

+		System.out.println(yyy);

+	}

+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull1/in/TestNoRedundantNonNull1.java b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull1/in/TestNoRedundantNonNull1.java
new file mode 100644
index 0000000..0f576c1
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull1/in/TestNoRedundantNonNull1.java
@@ -0,0 +1,22 @@
+package p;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+@NonNullByDefault({ PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT, ARRAY_CONTENTS })
+class TestNoRedundantNonNull1 {
+	String string = "A";
+	Integer integer = 2;
+	Map<String, ? extends Number> map = new HashMap<>();
+	Object[][] array = { {}, {} };
+
+	void foo(String s1, Integer h1, Map<String, ? extends Number> map1, Object[][] array1) {
+		string = s1;
+		integer = h1;
+		map = map1;
+		array = array1;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull1/out/FooParameter.java b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull1/out/FooParameter.java
new file mode 100644
index 0000000..f7d5185
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull1/out/FooParameter.java
@@ -0,0 +1,30 @@
+package p;
+
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNull;
+
+public class FooParameter {
+	private @NonNull String s1;
+	private @NonNull Integer h1;
+	private @NonNull Map<@NonNull String, ? extends @NonNull Number> map1;
+	private @NonNull Object @NonNull [] @NonNull [] array1;
+	public FooParameter(@NonNull String s1, @NonNull Integer h1, @NonNull Map<@NonNull String, ? extends @NonNull Number> map1, @NonNull Object @NonNull [] @NonNull [] array1) {
+		this.s1 = s1;
+		this.h1 = h1;
+		this.map1 = map1;
+		this.array1 = array1;
+	}
+	public @NonNull String getS1() {
+		return s1;
+	}
+	public @NonNull Integer getH1() {
+		return h1;
+	}
+	public @NonNull Map<@NonNull String, ? extends @NonNull Number> getMap1() {
+		return map1;
+	}
+	public @NonNull Object @NonNull [] @NonNull [] getArray1() {
+		return array1;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull1/out/TestNoRedundantNonNull1.java b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull1/out/TestNoRedundantNonNull1.java
new file mode 100644
index 0000000..027ea10
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull1/out/TestNoRedundantNonNull1.java
@@ -0,0 +1,22 @@
+package p;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+@NonNullByDefault({ PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT, ARRAY_CONTENTS })
+class TestNoRedundantNonNull1 {
+	String string = "A";
+	Integer integer = 2;
+	Map<String, ? extends Number> map = new HashMap<>();
+	Object[][] array = { {}, {} };
+
+	void foo(FooParameter parameterObject) {
+		string = parameterObject.getS1();
+		integer = parameterObject.getH1();
+		map = parameterObject.getMap1();
+		array = parameterObject.getArray1();
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull2/in/TestNoRedundantNonNull2.java b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull2/in/TestNoRedundantNonNull2.java
new file mode 100644
index 0000000..50b8ea0
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull2/in/TestNoRedundantNonNull2.java
@@ -0,0 +1,22 @@
+package p;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+@NonNullByDefault({ PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT, ARRAY_CONTENTS })
+class TestNoRedundantNonNull2 {
+	String string = "A";
+	Integer integer = 2;
+	Map<String, ? extends Number> map = new HashMap<>();
+	Object[][] array = { {}, {} };
+
+	void foo(String s1, Integer h1, Map<String, ? extends Number> map1, Object[][] array1) {
+		string = s1;
+		integer = h1;
+		map = map1;
+		array = array1;
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull2/out/TestNoRedundantNonNull2.java b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull2/out/TestNoRedundantNonNull2.java
new file mode 100644
index 0000000..caedd57
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/IntroduceParameterObject18/testNoRedundantNonNull2/out/TestNoRedundantNonNull2.java
@@ -0,0 +1,47 @@
+package p;
+
+import static org.eclipse.jdt.annotation.DefaultLocation.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+@NonNullByDefault({ PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT, ARRAY_CONTENTS })
+class TestNoRedundantNonNull2 {
+	String string = "A";
+	Integer integer = 2;
+	Map<String, ? extends Number> map = new HashMap<>();
+	Object[][] array = { {}, {} };
+
+	public static class FooParameter {
+		private String s1;
+		private Integer h1;
+		private Map<String, ? extends Number> map1;
+		private Object[][] array1;
+		public FooParameter(String s1, Integer h1, Map<String, ? extends Number> map1, Object[][] array1) {
+			this.s1 = s1;
+			this.h1 = h1;
+			this.map1 = map1;
+			this.array1 = array1;
+		}
+		public String getS1() {
+			return s1;
+		}
+		public Integer getH1() {
+			return h1;
+		}
+		public Map<String, ? extends Number> getMap1() {
+			return map1;
+		}
+		public Object[][] getArray1() {
+			return array1;
+		}
+	}
+
+	void foo(FooParameter parameterObject) {
+		string = parameterObject.getS1();
+		integer = parameterObject.getH1();
+		map = parameterObject.getMap1();
+		array = parameterObject.getArray1();
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractClassTests.java b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractClassTests.java
index 412dda0..ca5c4dd 100644
--- a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractClassTests.java
+++ b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractClassTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2013 IBM Corporation and others.
+ * Copyright (c) 2007, 2017 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
@@ -44,8 +44,8 @@
 public class ExtractClassTests extends RefactoringTest {
 
 	private static final String REFACTORING_PATH= "ExtractClass/";
-	private IPackageFragment fPack;
-	private ExtractClassDescriptor fDescriptor;
+	protected IPackageFragment fPack;
+	protected ExtractClassDescriptor fDescriptor;
 
 	public ExtractClassTests(String name) {
 		super(name);
@@ -59,7 +59,7 @@
 		return new RefactoringTestSetup(someTest);
 	}
 
-	private IType setupType() throws Exception {
+	protected IType setupType() throws Exception {
 		ICompilationUnit cu= createCUfromTestFile(getPackageP(), getCUName(), true);
 		IType type= cu.getType(getCUName());
 		assertNotNull(type);
@@ -109,7 +109,7 @@
 		return pack;
 	}
 
-	private String getCUName() {
+	protected String getCUName() {
 		StringBuffer sb= new StringBuffer();
 		String name= getName();
 		if (name.startsWith("test"))
@@ -118,14 +118,14 @@
 		return sb.toString();
 	}
 
-	private String getCUFileName() {
+	protected String getCUFileName() {
 		StringBuffer sb= new StringBuffer();
 		sb.append(getCUName());
 		sb.append(".java");
 		return sb.toString();
 	}
 
-	private RefactoringStatus runRefactoring(boolean expectError) throws Exception {
+	protected RefactoringStatus runRefactoring(boolean expectError) throws Exception {
 		RefactoringStatus status= performRefactoring(fDescriptor);
 		if (expectError) {
 			assertNotNull(status + "", status);
diff --git a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractClassTests18.java b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractClassTests18.java
new file mode 100644
index 0000000..4375d88
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractClassTests18.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Till Brychcy 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:
+ *     Till Brychcy - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.ui.tests.refactoring;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.jdt.testplugin.JavaProjectHelper;
+
+import org.eclipse.core.runtime.Path;
+
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+
+import org.eclipse.jdt.ui.tests.core.Java18ProjectTestSetup;
+
+import junit.framework.Test;
+
+public class ExtractClassTests18 extends ExtractClassTests {
+
+	private static final String REFACTORING_PATH= "ExtractClass18/";
+
+	public ExtractClassTests18(String name) {
+		super(name);
+	}
+
+	public static Test suite() {
+		return new Java18Setup(new NoSuperTestsSuite(ExtractClassTests18.class));
+	}
+
+	public static Test setUpTest(Test someTest) {
+		return new Java18Setup(someTest);
+	}
+
+	@Override
+	protected String getRefactoringPath() {
+		return REFACTORING_PATH;
+	}
+
+	/* Test that @NonNull annotations ARE created if no @NonNullByDefault is in effect for the target location */  
+	public void testNoRedundantNonNull1() throws Exception {
+		IJavaProject javaProject= getRoot().getJavaProject();
+		Map<String, String> originalOptions= javaProject.getOptions(false);
+		try {
+			Hashtable<String, String> newOptions= new Hashtable<>(originalOptions);
+			newOptions.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+			javaProject.setOptions(newOptions);
+			JavaProjectHelper.addLibrary(javaProject, new Path(Java18ProjectTestSetup.getJdtAnnotations20Path()));
+
+			fDescriptor.setType(setupType());
+			fDescriptor.setCreateGetterSetter(true);
+			fDescriptor.setClassName("NoRedundantNonNull1Data");
+			fDescriptor.setFieldName("data");
+			fDescriptor.setCreateTopLevel(true);
+			runRefactoring(false);
+		} finally {
+			javaProject.setOptions(originalOptions);
+		}
+	}
+
+	/* Test that @NonNull annotations ARE NOT created if @NonNullByDefault is in effect for the target location */  
+	public void testNoRedundantNonNull2() throws Exception {
+		IJavaProject javaProject= getRoot().getJavaProject();
+		Map<String, String> originalOptions= javaProject.getOptions(false);
+		try {
+			Hashtable<String, String> newOptions= new Hashtable<>(originalOptions);
+			newOptions.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+			javaProject.setOptions(newOptions);
+			JavaProjectHelper.addLibrary(javaProject, new Path(Java18ProjectTestSetup.getJdtAnnotations20Path()));
+
+			fDescriptor.setType(setupType());
+			fDescriptor.setCreateGetterSetter(true);
+			fDescriptor.setClassName("NoRedundantNonNull2Data");
+			fDescriptor.setFieldName("data");
+			fDescriptor.setCreateTopLevel(false);
+			runRefactoring(false);
+		} finally {
+			javaProject.setOptions(originalOptions);
+		}
+	}
+}
diff --git a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractMethodTests.java b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractMethodTests.java
index bd7632b..3ad38f7 100644
--- a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractMethodTests.java
+++ b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractMethodTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -1940,6 +1940,18 @@
 		duplicatesTest();
 	}
 
+	public void test990() throws Exception {
+		duplicatesTest();
+	}
+
+	public void test991() throws Exception {
+		duplicatesTest();
+	}
+
+	public void test992() throws Exception {
+		duplicatesTest();
+	}
+
 	//---- Test code in initializers -----------------------------------------------
 
 	public void test1000() throws Exception {
diff --git a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceParameterObjectTests.java b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceParameterObjectTests.java
index d549f96..0ec381d 100644
--- a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceParameterObjectTests.java
+++ b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceParameterObjectTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2015 IBM Corporation and others.
+ * Copyright (c) 2005, 2017 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
@@ -57,7 +57,7 @@
 	}
 
 	private IPackageFragment fPack;
-	private IntroduceParameterObjectDescriptor fDescriptor;
+	protected IntroduceParameterObjectDescriptor fDescriptor;
 
 	public IntroduceParameterObjectTests(String name) {
 		super(name);
@@ -123,7 +123,7 @@
 		return pack;
 	}
 
-	private void runRefactoring(boolean expectError, boolean useSuggestedMethod) throws Exception {
+	protected void runRefactoring(boolean expectError, boolean useSuggestedMethod) throws Exception {
 		RefactoringStatus status= performRefactoring(fDescriptor);
 		if (expectError) {
 			assertNotNull(status);
@@ -178,7 +178,7 @@
 		fPack= getPackageP();
 	}
 
-	private IMethod setupMethod() throws Exception, JavaModelException {
+	protected IMethod setupMethod() throws Exception, JavaModelException {
 		ICompilationUnit cu= createCUfromTestFile(fPack, getCUName(false), true);
 		IType type= cu.getType(getCUName(false));
 		assertNotNull(type);
diff --git a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceParameterObjectTests18.java b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceParameterObjectTests18.java
new file mode 100644
index 0000000..ae081c2
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/IntroduceParameterObjectTests18.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Till Brychcy 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:
+ *     Till Brychcy - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.ui.tests.refactoring;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.eclipse.jdt.testplugin.JavaProjectHelper;
+
+import org.eclipse.core.runtime.Path;
+
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+
+import org.eclipse.jdt.ui.tests.core.Java18ProjectTestSetup;
+
+import junit.framework.Test;
+
+public class IntroduceParameterObjectTests18 extends IntroduceParameterObjectTests {
+
+	private static final Class<IntroduceParameterObjectTests18> CLAZZ= IntroduceParameterObjectTests18.class;
+	private static final String REFACTORING_PATH= "IntroduceParameterObject18/";
+
+	public static Test setUpTest(Test someTest) {
+		return new Java18Setup(someTest);
+	}
+
+	public static Test suite() {
+		return new Java18Setup(new NoSuperTestsSuite(CLAZZ));
+	}
+
+	public IntroduceParameterObjectTests18(String name) {
+		super(name);
+	}
+
+
+	@Override
+	protected String getRefactoringPath() {
+		return REFACTORING_PATH;
+	}
+
+	/* Test that @NonNull annotations ARE created if no @NonNullByDefault is in effect for the target location */  
+	public void testNoRedundantNonNull1() throws Exception {
+		IJavaProject javaProject= getRoot().getJavaProject();
+		Map<String, String> originalOptions= javaProject.getOptions(false);
+		try {
+			Hashtable<String, String> newOptions= new Hashtable<>(originalOptions);
+			newOptions.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+			javaProject.setOptions(newOptions);
+			JavaProjectHelper.addLibrary(javaProject, new Path(Java18ProjectTestSetup.getJdtAnnotations20Path()));
+
+			fDescriptor.setMethod(setupMethod());
+			fDescriptor.setTopLevel(true);
+			fDescriptor.setGetters(true);
+			fDescriptor.setClassName("FooParameter");
+			runRefactoring(false, true);
+		} finally {
+			javaProject.setOptions(originalOptions);
+		}
+	}
+	/* Test that @NonNull annotations ARE NOT created if @NonNullByDefault is in effect for the target location */  
+	public void testNoRedundantNonNull2() throws Exception {
+		IJavaProject javaProject= getRoot().getJavaProject();
+		Map<String, String> originalOptions= javaProject.getOptions(false);
+		try {
+			Hashtable<String, String> newOptions= new Hashtable<>(originalOptions);
+			newOptions.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+			javaProject.setOptions(newOptions);
+			JavaProjectHelper.addLibrary(javaProject, new Path(Java18ProjectTestSetup.getJdtAnnotations20Path()));
+
+			fDescriptor.setMethod(setupMethod());
+			fDescriptor.setTopLevel(false);
+			fDescriptor.setGetters(true);
+			runRefactoring(false, true);
+		} finally {
+			javaProject.setOptions(originalOptions);
+		}
+	}
+}
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AnnotateAssistTest18.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AnnotateAssistTest18.java
index 102f86f..33719b6 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AnnotateAssistTest18.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/AnnotateAssistTest18.java
@@ -526,6 +526,150 @@
 	}
 
 	/**
+	 * Assert two proposals ("@NonNull" and "@Nullable") on an array type in normal syntax.
+	 * A two line entry using this selector & signature exists and will be amended.
+	 * Apply the second proposal and check the effect.
+	 * 
+	 * @throws Exception multiple causes
+	 */
+	public void testAnnotateMethod_Array1() throws Exception {
+		
+		String X_PATH= "pack/age/X";
+		String[] pathAndContents= new String[] {
+					X_PATH+".java",
+					"package pack.age;\n" +
+					"import java.util.List;\n" +
+					"public interface X {\n" +
+					"    public String[] test();\n" +
+					"}\n"
+				};
+		addLibrary(fJProject1, "lib.jar", "lib.zip", pathAndContents, ANNOTATION_PATH, JavaCore.VERSION_1_8, null);
+		
+		IFile annotationFile= fJProject1.getProject().getFile(new Path(ANNOTATION_PATH).append(X_PATH+".eea"));
+		String initialContent=
+				"class pack/age/X\n" +
+				"test\n" +
+				" ()[Ljava/lang/String;\n";
+		ensureExists(annotationFile.getParent());
+		annotationFile.create(new ByteArrayInputStream(initialContent.getBytes("UTF-8")), 0, null);
+
+		IType type= fJProject1.findType(X_PATH.replace('/', '.'));
+		JavaEditor javaEditor= (JavaEditor) JavaUI.openInEditor(type);
+
+		try {
+			int offset= pathAndContents[1].indexOf("[] test");
+
+			List<ICompletionProposal> list= collectAnnotateProposals(javaEditor, offset);
+			
+			assertCorrectLabels(list);
+			assertNumberOfProposals(list, 2);
+			
+			ICompletionProposal proposal= findProposalByName("Annotate as 'String @NonNull []'", list);
+			String expectedInfo=
+					"<dl><dt>test</dt>" +
+					"<dd>()[Ljava/lang/String;</dd>" +
+					"<dd>()[<b>1</b>Ljava/lang/String;</dd>" + // <= 1
+					"</dl>";
+			assertEquals("expect detail", expectedInfo, proposal.getAdditionalProposalInfo());
+
+			proposal= findProposalByName("Annotate as 'String @Nullable []'", list);
+			expectedInfo=
+					"<dl><dt>test</dt>" +
+					"<dd>()[Ljava/lang/String;</dd>" +
+					"<dd>()[<b>0</b>Ljava/lang/String;</dd>" + // <= 0
+					"</dl>";
+			assertEquals("expect detail", expectedInfo, proposal.getAdditionalProposalInfo());
+
+			IDocument document= javaEditor.getDocumentProvider().getDocument(javaEditor.getEditorInput());
+			proposal.apply(document);
+			
+			annotationFile= fJProject1.getProject().getFile(new Path(ANNOTATION_PATH).append(X_PATH+".eea"));
+			assertTrue("Annotation file should have been created", annotationFile.exists());
+
+			String expectedContent=
+					"class pack/age/X\n" +
+					"test\n" +
+					" ()[Ljava/lang/String;\n" +
+					" ()[0Ljava/lang/String;\n";
+			checkContentOfFile("annotation file content", annotationFile, expectedContent);
+		} finally {
+			JavaPlugin.getActivePage().closeAllEditors(false);
+		}
+	}
+
+	/**
+	 * Assert two proposals ("@NonNull" and "@Nullable") on an array type in extra-dims syntax.
+	 * A two line entry using this selector & signature exists and will be amended.
+	 * Apply the second proposal and check the effect.
+	 * 
+	 * @throws Exception multiple causes
+	 */
+	public void testAnnotateMethod_Array2() throws Exception {
+		
+		String X_PATH= "pack/age/X";
+		String[] pathAndContents= new String[] {
+					X_PATH+".java",
+					"package pack.age;\n" +
+					"import java.util.List;\n" +
+					"public interface X {\n" +
+					"    public String test()[];\n" +
+					"}\n"
+				};
+		addLibrary(fJProject1, "lib.jar", "lib.zip", pathAndContents, ANNOTATION_PATH, JavaCore.VERSION_1_8, null);
+		
+		IFile annotationFile= fJProject1.getProject().getFile(new Path(ANNOTATION_PATH).append(X_PATH+".eea"));
+		String initialContent=
+				"class pack/age/X\n" +
+				"test\n" +
+				" ()[Ljava/lang/String;\n";
+		ensureExists(annotationFile.getParent());
+		annotationFile.create(new ByteArrayInputStream(initialContent.getBytes("UTF-8")), 0, null);
+
+		IType type= fJProject1.findType(X_PATH.replace('/', '.'));
+		JavaEditor javaEditor= (JavaEditor) JavaUI.openInEditor(type);
+
+		try {
+			int offset= pathAndContents[1].indexOf("[];");
+
+			List<ICompletionProposal> list= collectAnnotateProposals(javaEditor, offset);
+			
+			assertCorrectLabels(list);
+			assertNumberOfProposals(list, 2);
+			
+			ICompletionProposal proposal= findProposalByName("Annotate as 'String @NonNull []'", list);
+			String expectedInfo=
+					"<dl><dt>test</dt>" +
+					"<dd>()[Ljava/lang/String;</dd>" +
+					"<dd>()[<b>1</b>Ljava/lang/String;</dd>" + // <= 1
+					"</dl>";
+			assertEquals("expect detail", expectedInfo, proposal.getAdditionalProposalInfo());
+
+			proposal= findProposalByName("Annotate as 'String @Nullable []'", list);
+			expectedInfo=
+					"<dl><dt>test</dt>" +
+					"<dd>()[Ljava/lang/String;</dd>" +
+					"<dd>()[<b>0</b>Ljava/lang/String;</dd>" + // <= 0
+					"</dl>";
+			assertEquals("expect detail", expectedInfo, proposal.getAdditionalProposalInfo());
+
+			IDocument document= javaEditor.getDocumentProvider().getDocument(javaEditor.getEditorInput());
+			proposal.apply(document);
+			
+			annotationFile= fJProject1.getProject().getFile(new Path(ANNOTATION_PATH).append(X_PATH+".eea"));
+			assertTrue("Annotation file should have been created", annotationFile.exists());
+
+			String expectedContent=
+					"class pack/age/X\n" +
+					"test\n" +
+					" ()[Ljava/lang/String;\n" +
+					" ()[0Ljava/lang/String;\n";
+			checkContentOfFile("annotation file content", annotationFile, expectedContent);
+		} finally {
+			JavaPlugin.getActivePage().closeAllEditors(false);
+		}
+	}
+
+	/**
 	 * Assert two proposals ("@NonNull" and "@Nullable") on the array representing the varargs ellipsis
 	 * Apply the second proposal and check the effect.
 	 * 
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 dfa33cf..154d8cd 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2016 IBM Corporation and others.
+ * Copyright (c) 2013, 2017 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
@@ -18,6 +18,7 @@
 import org.eclipse.jdt.testplugin.JavaProjectHelper;
 import org.eclipse.jdt.testplugin.TestOptions;
 
+import org.eclipse.core.runtime.Path;
 import org.eclipse.jface.preference.IPreferenceStore;
 
 import org.eclipse.jdt.core.ICompilationUnit;
@@ -4555,4 +4556,625 @@
 		assertProposalDoesNotExist(proposals, CorrectionMessages.QuickAssistProcessor_removeParenthesesInLambda);
 	}
 
+	public void testBug514203_wildCard() throws Exception {
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+		StringBuffer buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.util.Comparator;\n");
+		buf.append("import java.util.List;\n");
+		buf.append("\n");
+		buf.append("public class Lambda1 {\n");
+		buf.append("	Comparator<List<?>> c = (l1, l2) -> Integer.compare(l1.size(), l2.size());\n");
+		buf.append("}\n");
+		ICompilationUnit cu= pack1.createCompilationUnit("Lambda1.java", buf.toString(), false, null);
+
+		AssistContext context= getCorrectionContext(cu, buf.toString().indexOf("->"), 0);
+		assertNoErrors(context);
+		List<IJavaCompletionProposal> proposals= collectAssists(context, false);
+
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.util.Comparator;\n");
+		buf.append("import java.util.List;\n");
+		buf.append("\n");
+		buf.append("public class Lambda1 {\n");
+		buf.append("	Comparator<List<?>> c = (List<?> l1, List<?> l2) -> Integer.compare(l1.size(), l2.size());\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Add inferred lambda parameter types", proposals);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.util.Comparator;\n");
+		buf.append("import java.util.List;\n");
+		buf.append("\n");
+		buf.append("public class Lambda1 {\n");
+		buf.append("	Comparator<List<?>> c = new Comparator<List<?>>() {\n");
+		buf.append("        @Override\n");
+		buf.append("        public int compare(List<?> l1, List<?> l2) {\n");
+		buf.append("            return Integer.compare(l1.size(), l2.size());\n");
+		buf.append("        }\n");
+		buf.append("    };\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Convert to anonymous class creation", proposals);
+		
+	}
+
+	public void testBug514203_capture1() throws Exception {
+		Hashtable<String, String> options= JavaCore.getOptions();
+		options.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+		JavaCore.setOptions(options);
+		JavaProjectHelper.addLibrary(fJProject1, new Path(Java18ProjectTestSetup.getJdtAnnotations20Path()));
+		
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+
+		StringBuffer buf;
+
+		buf= new StringBuffer();
+		buf.append("@org.eclipse.jdt.annotation.NonNullByDefault\n");
+		buf.append("package test1;\n");
+		pack1.createCompilationUnit("package-info.java", buf.toString(), false, null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("public class Lambda2 {\n");
+		buf.append("	interface Sink<T> {\n");
+		buf.append("		void receive(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	interface Source<U> {\n");
+		buf.append("		void sendTo(Sink<? super U> c);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	void f(Source<? extends Number> source) {\n");
+		buf.append("		source.sendTo(a -> a.doubleValue());\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		ICompilationUnit cu= pack1.createCompilationUnit("Lambda2.java", buf.toString(), false, null);
+
+		AssistContext context= getCorrectionContext(cu, buf.toString().indexOf("->"), 0);
+		assertNoErrors(context);
+		List<IJavaCompletionProposal> proposals= collectAssists(context, false);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("public class Lambda2 {\n");
+		buf.append("	interface Sink<T> {\n");
+		buf.append("		void receive(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	interface Source<U> {\n");
+		buf.append("		void sendTo(Sink<? super U> c);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	void f(Source<? extends Number> source) {\n");
+		buf.append("		source.sendTo(Number::doubleValue);\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Convert to method reference", proposals);
+
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("public class Lambda2 {\n");
+		buf.append("	interface Sink<T> {\n");
+		buf.append("		void receive(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	interface Source<U> {\n");
+		buf.append("		void sendTo(Sink<? super U> c);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	void f(Source<? extends Number> source) {\n");
+		buf.append("		source.sendTo((Number a) -> a.doubleValue());\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Add inferred lambda parameter types", proposals);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("public class Lambda2 {\n");
+		buf.append("	interface Sink<T> {\n");
+		buf.append("		void receive(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	interface Source<U> {\n");
+		buf.append("		void sendTo(Sink<? super U> c);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	void f(Source<? extends Number> source) {\n");
+		buf.append("		source.sendTo(new Sink<Number>() {\n");
+		buf.append("            @Override\n");
+		buf.append("            public void receive(Number a) {\n");
+		buf.append("                a.doubleValue();\n");
+		buf.append("            }\n");
+		buf.append("        });\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Convert to anonymous class creation", proposals);
+		
+	}
+
+	public void testBug514203_capture2() throws Exception {
+		Hashtable<String, String> options= JavaCore.getOptions();
+		options.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+		JavaCore.setOptions(options);
+		JavaProjectHelper.addLibrary(fJProject1, new Path(Java18ProjectTestSetup.getJdtAnnotations20Path()));
+		
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+
+		StringBuffer buf;
+
+		buf= new StringBuffer();
+		buf.append("@org.eclipse.jdt.annotation.NonNullByDefault\n");
+		buf.append("package test1;\n");
+		pack1.createCompilationUnit("package-info.java", buf.toString(), false, null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.math.BigDecimal;\n");
+		buf.append("\n");
+		buf.append("public class Lambda3 {\n");
+		buf.append("	interface Sink<T extends Number> {\n");
+		buf.append("		void receive(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	interface Source<U extends BigDecimal> {\n");
+		buf.append("		void sendTo(Sink<? super U> c);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	void f(Source<?> source) {\n");
+		buf.append("		source.sendTo(a -> a.scale());\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		ICompilationUnit cu= pack1.createCompilationUnit("Lambda3.java", buf.toString(), false, null);
+
+		AssistContext context= getCorrectionContext(cu, buf.toString().indexOf("->"), 0);
+		assertNoErrors(context);
+		List<IJavaCompletionProposal> proposals= collectAssists(context, false);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.math.BigDecimal;\n");
+		buf.append("\n");
+		buf.append("public class Lambda3 {\n");
+		buf.append("	interface Sink<T extends Number> {\n");
+		buf.append("		void receive(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	interface Source<U extends BigDecimal> {\n");
+		buf.append("		void sendTo(Sink<? super U> c);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	void f(Source<?> source) {\n");
+		buf.append("		source.sendTo(BigDecimal::scale);\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Convert to method reference", proposals);
+
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.math.BigDecimal;\n");
+		buf.append("\n");
+		buf.append("public class Lambda3 {\n");
+		buf.append("	interface Sink<T extends Number> {\n");
+		buf.append("		void receive(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	interface Source<U extends BigDecimal> {\n");
+		buf.append("		void sendTo(Sink<? super U> c);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	void f(Source<?> source) {\n");
+		buf.append("		source.sendTo((BigDecimal a) -> a.scale());\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Add inferred lambda parameter types", proposals);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.math.BigDecimal;\n");
+		buf.append("\n");
+		buf.append("public class Lambda3 {\n");
+		buf.append("	interface Sink<T extends Number> {\n");
+		buf.append("		void receive(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	interface Source<U extends BigDecimal> {\n");
+		buf.append("		void sendTo(Sink<? super U> c);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	void f(Source<?> source) {\n");
+		buf.append("		source.sendTo(new Sink<BigDecimal>() {\n");
+		buf.append("            @Override\n");
+		buf.append("            public void receive(BigDecimal a) {\n");
+		buf.append("                a.scale();\n");
+		buf.append("            }\n");
+		buf.append("        });\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Convert to anonymous class creation", proposals);
+		
+	}
+
+	public void testBug514203_capture3() throws Exception {
+		Hashtable<String, String> options= JavaCore.getOptions();
+		options.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+		JavaCore.setOptions(options);
+		JavaProjectHelper.addLibrary(fJProject1, new Path(Java18ProjectTestSetup.getJdtAnnotations20Path()));
+		
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+
+		StringBuffer buf;
+
+		buf= new StringBuffer();
+		buf.append("@org.eclipse.jdt.annotation.NonNullByDefault\n");
+		buf.append("package test1;\n");
+		pack1.createCompilationUnit("package-info.java", buf.toString(), false, null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.util.ArrayList;\n");
+		buf.append("import java.util.List;\n");
+		buf.append("\n");
+		buf.append("public class Lambda4 {\n");
+		buf.append("	interface Sink<T extends List<Number>> {\n");
+		buf.append("		void receive(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	interface Source<U extends ArrayList<Number>> {\n");
+		buf.append("		void sendTo(Sink<? super U> c);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	void f(Source<?> source) {\n");
+		buf.append("		source.sendTo(a -> a.size());\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		ICompilationUnit cu= pack1.createCompilationUnit("Lambda4.java", buf.toString(), false, null);
+
+		AssistContext context= getCorrectionContext(cu, buf.toString().indexOf("->"), 0);
+		assertNoErrors(context);
+		List<IJavaCompletionProposal> proposals= collectAssists(context, false);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.util.ArrayList;\n");
+		buf.append("import java.util.List;\n");
+		buf.append("\n");
+		buf.append("public class Lambda4 {\n");
+		buf.append("	interface Sink<T extends List<Number>> {\n");
+		buf.append("		void receive(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	interface Source<U extends ArrayList<Number>> {\n");
+		buf.append("		void sendTo(Sink<? super U> c);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	void f(Source<?> source) {\n");
+		buf.append("		source.sendTo(ArrayList<Number>::size);\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Convert to method reference", proposals);
+
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.util.ArrayList;\n");
+		buf.append("import java.util.List;\n");
+		buf.append("\n");
+		buf.append("public class Lambda4 {\n");
+		buf.append("	interface Sink<T extends List<Number>> {\n");
+		buf.append("		void receive(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	interface Source<U extends ArrayList<Number>> {\n");
+		buf.append("		void sendTo(Sink<? super U> c);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	void f(Source<?> source) {\n");
+		buf.append("		source.sendTo((ArrayList<Number> a) -> a.size());\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Add inferred lambda parameter types", proposals);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.util.ArrayList;\n");
+		buf.append("import java.util.List;\n");
+		buf.append("\n");
+		buf.append("public class Lambda4 {\n");
+		buf.append("	interface Sink<T extends List<Number>> {\n");
+		buf.append("		void receive(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	interface Source<U extends ArrayList<Number>> {\n");
+		buf.append("		void sendTo(Sink<? super U> c);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	void f(Source<?> source) {\n");
+		buf.append("		source.sendTo(new Sink<ArrayList<Number>>() {\n");
+		buf.append("            @Override\n");
+		buf.append("            public void receive(ArrayList<Number> a) {\n");
+		buf.append("                a.size();\n");
+		buf.append("            }\n");
+		buf.append("        });\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Convert to anonymous class creation", proposals);
+		
+	}
+
+	public void testBug514203_lambdaNN() throws Exception {
+		Hashtable<String, String> options= JavaCore.getOptions();
+		options.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+		JavaCore.setOptions(options);
+		JavaProjectHelper.addLibrary(fJProject1, new Path(Java18ProjectTestSetup.getJdtAnnotations20Path()));
+		
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+
+		StringBuffer buf;
+
+		// --- Set up @NonNullByDefault for the package, including ARRAY_CONTENTS --
+
+		buf= new StringBuffer();
+		buf.append("@NonNullByDefault({ PARAMETER, RETURN_TYPE, FIELD, TYPE_BOUND, TYPE_ARGUMENT, ARRAY_CONTENTS })\n");
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import static org.eclipse.jdt.annotation.DefaultLocation.*;\n");
+		buf.append("import org.eclipse.jdt.annotation.NonNullByDefault;\n");
+		pack1.createCompilationUnit("package-info.java", buf.toString(), false, null);
+
+		// --- Classes that are only referenced --
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.lang.annotation.ElementType;\n");
+		buf.append("import java.lang.annotation.Target;\n");
+		buf.append("\n");
+		buf.append("@Target(ElementType.TYPE_USE)\n");
+		buf.append("@interface X {}\n");
+		pack1.createCompilationUnit("X.java", buf.toString(), false, null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.lang.annotation.ElementType;\n");
+		buf.append("import java.lang.annotation.Target;\n");
+		buf.append("\n");
+		buf.append("@Target(ElementType.TYPE_USE)\n");
+		buf.append("@interface Y {}\n");
+		pack1.createCompilationUnit("Y.java", buf.toString(), false, null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.lang.annotation.ElementType;\n");
+		buf.append("import java.lang.annotation.Target;\n");
+		buf.append("\n");
+		buf.append("@Target(ElementType.TYPE_USE)\n");
+		buf.append("@interface Z {}\n");
+		pack1.createCompilationUnit("Z.java", buf.toString(), false, null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("class Ref<A> {}\n");
+		pack1.createCompilationUnit("Ref.java", buf.toString(), false, null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("interface SAM<A> {\n");
+		buf.append("	void f(A[] a);\n");
+		buf.append("}\n");
+		pack1.createCompilationUnit("SAM.java", buf.toString(), false, null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("public class Test {\n");
+		buf.append("	static int nn(Object o) {\n");
+		buf.append("		return 0;\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		buf.append("");
+		pack1.createCompilationUnit("Test.java", buf.toString(), false, null);
+
+		// --- Classes in which the quick assists are checked (without and with NonNullByDefault in effect at the target location) --- 
+		
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("public class LambdaNN1 {\n");
+		buf.append("	void g(Ref<? extends Ref<@X @Nullable String @Y [] @Z []>>[] data) {\n");
+		buf.append("		@NonNullByDefault({})\n");
+		buf.append("		SAM<? super @NonNull Ref<? extends @NonNull @Y Ref<@X @Nullable String @Y @NonNull [] @Z @NonNull []>>> sam0 = a0 -> Test.nn(a0);\n");
+		buf.append("		sam0.f(data);\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		ICompilationUnit cu1= pack1.createCompilationUnit("LambdaNN1.java", buf.toString(), false, null);
+
+		AssistContext context1= getCorrectionContext(cu1, buf.toString().indexOf("->"), 0);
+		assertNoErrors(context1);
+		List<IJavaCompletionProposal> proposals1= collectAssists(context1, false);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("public class LambdaNN2 {\n");
+		buf.append("	void g(Ref<? extends Ref<@X @Nullable String @Y [] @Z []>>[] data) {\n");
+		buf.append("		SAM<? super @NonNull Ref<? extends @NonNull @Y Ref<@X @Nullable String @Y @NonNull [] @Z @NonNull []>>> sam0 = a0 -> Test.nn(a0);\n");
+		buf.append("		sam0.f(data);\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		ICompilationUnit cu2= pack1.createCompilationUnit("LambdaNN2.java", buf.toString(), false, null);
+
+		AssistContext context2= getCorrectionContext(cu2, buf.toString().indexOf("->"), 0);
+		assertNoErrors(context2);
+
+		List<IJavaCompletionProposal> proposals2= collectAssists(context2, false);
+
+		// --- Convert to method reference without and with NNBD ---
+		
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("public class LambdaNN1 {\n");
+		buf.append("	void g(Ref<? extends Ref<@X @Nullable String @Y [] @Z []>>[] data) {\n");
+		buf.append("		@NonNullByDefault({})\n");
+		buf.append("		SAM<? super @NonNull Ref<? extends @NonNull @Y Ref<@X @Nullable String @Y @NonNull [] @Z @NonNull []>>> sam0 = Test::nn;\n");
+		buf.append("		sam0.f(data);\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Convert to method reference", proposals1);
+
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("public class LambdaNN2 {\n");
+		buf.append("	void g(Ref<? extends Ref<@X @Nullable String @Y [] @Z []>>[] data) {\n");
+		buf.append("		SAM<? super @NonNull Ref<? extends @NonNull @Y Ref<@X @Nullable String @Y @NonNull [] @Z @NonNull []>>> sam0 = Test::nn;\n");
+		buf.append("		sam0.f(data);\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Convert to method reference", proposals2);
+
+		// --- Add inferred lambda parameter types without and with NNBD ---
+		
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("public class LambdaNN1 {\n");
+		buf.append("	void g(Ref<? extends Ref<@X @Nullable String @Y [] @Z []>>[] data) {\n");
+		buf.append("		@NonNullByDefault({})\n");
+		buf.append("		SAM<? super @NonNull Ref<? extends @NonNull @Y Ref<@X @Nullable String @Y @NonNull [] @Z @NonNull []>>> sam0 = (@NonNull Ref<? extends @NonNull @Y Ref<@X @Nullable String @Y @NonNull [] @Z @NonNull []>> @NonNull [] a0) -> Test.nn(a0);\n");
+		buf.append("		sam0.f(data);\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Add inferred lambda parameter types", proposals1);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("public class LambdaNN2 {\n");
+		buf.append("	void g(Ref<? extends Ref<@X @Nullable String @Y [] @Z []>>[] data) {\n");
+		buf.append("		SAM<? super @NonNull Ref<? extends @NonNull @Y Ref<@X @Nullable String @Y @NonNull [] @Z @NonNull []>>> sam0 = (Ref<? extends @Y Ref<@X @Nullable String @Y [] @Z []>>[] a0) -> Test.nn(a0);\n");
+		buf.append("		sam0.f(data);\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Add inferred lambda parameter types", proposals2);
+
+		// --- Convert to anonymous class creation without and with NNBD --
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("public class LambdaNN1 {\n");
+		buf.append("	void g(Ref<? extends Ref<@X @Nullable String @Y [] @Z []>>[] data) {\n");
+		buf.append("		@NonNullByDefault({})\n");
+		buf.append("		SAM<? super @NonNull Ref<? extends @NonNull @Y Ref<@X @Nullable String @Y @NonNull [] @Z @NonNull []>>> sam0 = new SAM<@NonNull Ref<? extends @NonNull @Y Ref<@X @Nullable String @Y @NonNull [] @Z @NonNull []>>>() {\n");
+		buf.append("            @Override\n");
+		buf.append("            public void f(\n");
+		buf.append("                    @NonNull Ref<? extends @NonNull @Y Ref<@X @Nullable String @Y @NonNull [] @Z @NonNull []>> @NonNull [] a0) {\n");
+		buf.append("                Test.nn(a0);\n");
+		buf.append("            }\n");
+		buf.append("        };\n");
+		buf.append("		sam0.f(data);\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Convert to anonymous class creation", proposals1);
+		
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("public class LambdaNN2 {\n");
+		buf.append("	void g(Ref<? extends Ref<@X @Nullable String @Y [] @Z []>>[] data) {\n");
+		buf.append("		SAM<? super @NonNull Ref<? extends @NonNull @Y Ref<@X @Nullable String @Y @NonNull [] @Z @NonNull []>>> sam0 = new SAM<Ref<? extends @Y Ref<@X @Nullable String @Y [] @Z []>>>() {\n");
+		buf.append("            @Override\n");
+		buf.append("            public void f(\n");
+		buf.append("                    Ref<? extends @Y Ref<@X @Nullable String @Y [] @Z []>>[] a0) {\n");
+		buf.append("                Test.nn(a0);\n");
+		buf.append("            }\n");
+		buf.append("        };\n");
+		buf.append("		sam0.f(data);\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Convert to anonymous class creation", proposals2);
+	}
+	public void testBug514203_annotatedParametrizedType() throws Exception {
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+		StringBuffer buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("public class Example {\n");
+		buf.append("	@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE)\n");
+		buf.append("	public @interface X {}\n");
+		buf.append("\n");
+		buf.append("	interface SAM<T> {\n");
+		buf.append("		T f(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	@X\n");
+		buf.append("	SAM<String> c = a -> a;\n");
+		buf.append("}\n");
+		ICompilationUnit cu= pack1.createCompilationUnit("Example.java", buf.toString(), false, null);
+
+		AssistContext context= getCorrectionContext(cu, buf.toString().indexOf("->"), 0);
+		assertNoErrors(context);
+		List<IJavaCompletionProposal> proposals= collectAssists(context, false);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("public class Example {\n");
+		buf.append("	@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE)\n");
+		buf.append("	public @interface X {}\n");
+		buf.append("\n");
+		buf.append("	interface SAM<T> {\n");
+		buf.append("		T f(T t);\n");
+		buf.append("	}\n");
+		buf.append("\n");
+		buf.append("	@X\n");
+		buf.append("	SAM<String> c = new @X SAM<String>() {\n");
+		buf.append("        @Override\n");
+		buf.append("        public String f(String a) {\n");
+		buf.append("            return a;\n");
+		buf.append("        }\n");
+		buf.append("    };\n");
+		buf.append("}\n");
+		assertProposalPreviewEquals(buf.toString(), "Convert to anonymous class creation", proposals);		
+	}
 }
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/NullAnnotationsQuickFixTest18.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/NullAnnotationsQuickFixTest18.java
index ea2f105..b746886 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/NullAnnotationsQuickFixTest18.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/NullAnnotationsQuickFixTest18.java
@@ -952,4 +952,241 @@
 		buf.append("}\n");
 		assertEqualString(preview, buf.toString());
 	}
+	public void testBug513682() throws Exception {
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+		StringBuffer buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("@NonNullByDefault\n");
+		buf.append("public class Test {\n");
+		buf.append("    void foo(Object o) {\n");
+		buf.append("      if(o != null) {\n");
+		buf.append("          o.hashCode();\n");
+		buf.append("      }\n");
+		buf.append("    }\n");
+		buf.append("}\n");
+		ICompilationUnit cu=pack1.createCompilationUnit("Test.java", buf.toString(), false, null);
+
+		CompilationUnit astRoot= getASTRoot(cu);
+		ArrayList<IJavaCompletionProposal> proposals= collectCorrections(cu, astRoot);
+		assertNumberOfProposals(proposals, 3);
+		CUCorrectionProposal proposal= (CUCorrectionProposal)proposals.get(0);
+
+		assertEqualString(proposal.getDisplayString(), "Change parameter 'o' to '@Nullable'");
+
+		String preview= getPreviewContent(proposal);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("@NonNullByDefault\n");
+		buf.append("public class Test {\n");
+		buf.append("    void foo(@Nullable Object o) {\n");
+		buf.append("      if(o != null) {\n");
+		buf.append("          o.hashCode();\n");
+		buf.append("      }\n");
+		buf.append("    }\n");
+		buf.append("}\n");
+		assertEqualString(preview, buf.toString());
+	}
+
+	public void testBug513209a() throws Exception {
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+		StringBuffer buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("public class A {\n");
+		buf.append("   public void SomeMethod(\n");
+		buf.append("      String[] a)\n");
+		buf.append("   {\n");
+		buf.append("\n");
+		buf.append("   }\n");
+		buf.append("}\n");
+		pack1.createCompilationUnit("A.java", buf.toString(), false, null);
+
+		buf = new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("@NonNullByDefault\n");
+		buf.append("public class B extends A {\n");
+		buf.append("   @Override\n");
+		buf.append("   public void SomeMethod(\n"); 
+		buf.append("      String[] a)\n"); 
+		buf.append("   {\n");
+		buf.append("\n");
+		buf.append("   }\n"); 
+		buf.append("}\n");
+		ICompilationUnit cu=pack1.createCompilationUnit("B.java", buf.toString(), false, null);
+
+		CompilationUnit astRoot= getASTRoot(cu);
+		ArrayList<IJavaCompletionProposal> proposals= collectCorrections(cu, astRoot);
+		assertNumberOfProposals(proposals, 3);
+		CUCorrectionProposal proposal= (CUCorrectionProposal)proposals.get(0);
+
+		assertEqualString(proposal.getDisplayString(), "Change parameter 'a' to '@Nullable'");
+
+		String preview= getPreviewContent(proposal);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("@NonNullByDefault\n");
+		buf.append("public class B extends A {\n");
+		buf.append("   @Override\n");
+		buf.append("   public void SomeMethod(\n"); 
+		buf.append("      String @Nullable [] a)\n"); 
+		buf.append("   {\n");
+		buf.append("\n");
+		buf.append("   }\n"); 
+		buf.append("}\n");
+		assertEqualString(preview, buf.toString());
+	}
+
+	public void testBug513209b() throws Exception {
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+		StringBuffer buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("public class A {\n");
+		buf.append("   public void SomeMethod(\n");
+		buf.append("      int[][] a)\n");
+		buf.append("   {\n");
+		buf.append("\n");
+		buf.append("   }\n");
+		buf.append("}\n");
+		pack1.createCompilationUnit("A.java", buf.toString(), false, null);
+
+		buf = new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("@NonNullByDefault\n");
+		buf.append("public class B extends A {\n");
+		buf.append("   @Override\n");
+		buf.append("   public void SomeMethod(\n"); 
+		buf.append("      int[][] a)\n"); 
+		buf.append("   {\n");
+		buf.append("\n");
+		buf.append("   }\n"); 
+		buf.append("}\n");
+		ICompilationUnit cu=pack1.createCompilationUnit("B.java", buf.toString(), false, null);
+
+		CompilationUnit astRoot= getASTRoot(cu);
+		ArrayList<IJavaCompletionProposal> proposals= collectCorrections(cu, astRoot);
+		assertNumberOfProposals(proposals, 3);
+		CUCorrectionProposal proposal= (CUCorrectionProposal)proposals.get(0);
+
+		assertEqualString(proposal.getDisplayString(), "Change parameter 'a' to '@Nullable'");
+
+		String preview= getPreviewContent(proposal);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("@NonNullByDefault\n");
+		buf.append("public class B extends A {\n");
+		buf.append("   @Override\n");
+		buf.append("   public void SomeMethod(\n"); 
+		buf.append("      int @Nullable [][] a)\n"); 
+		buf.append("   {\n");
+		buf.append("\n");
+		buf.append("   }\n"); 
+		buf.append("}\n");
+		assertEqualString(preview, buf.toString());
+	}
+
+	public void testBug513209c() throws Exception {
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+		StringBuffer buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("public class A {\n");
+		buf.append("   public void SomeMethod(\n");
+		buf.append("      String[] a)\n");
+		buf.append("   {\n");
+		buf.append("\n");
+		buf.append("   }\n");
+		buf.append("}\n");
+		pack1.createCompilationUnit("A.java", buf.toString(), false, null);
+
+		buf = new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("public class B extends A {\n");
+		buf.append("   @Override\n");
+		buf.append("   public void SomeMethod(\n"); 
+		buf.append("      String @NonNull [] a)\n"); 
+		buf.append("   {\n");
+		buf.append("\n");
+		buf.append("   }\n"); 
+		buf.append("}\n");
+		ICompilationUnit cu=pack1.createCompilationUnit("B.java", buf.toString(), false, null);
+
+		CompilationUnit astRoot= getASTRoot(cu);
+		ArrayList<IJavaCompletionProposal> proposals= collectCorrections(cu, astRoot);
+		assertNumberOfProposals(proposals, 3);
+		CUCorrectionProposal proposal= (CUCorrectionProposal)proposals.get(0);
+
+		assertEqualString(proposal.getDisplayString(), "Change parameter 'a' to '@Nullable'");
+
+		String preview= getPreviewContent(proposal);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("public class B extends A {\n");
+		buf.append("   @Override\n");
+		buf.append("   public void SomeMethod(\n"); 
+		buf.append("      String @Nullable [] a)\n"); 
+		buf.append("   {\n");
+		buf.append("\n");
+		buf.append("   }\n"); 
+		buf.append("}\n");
+		assertEqualString(preview, buf.toString());
+	}
+
+	public void testBug513209d() throws Exception {
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+		StringBuffer buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("@NonNullByDefault\n");
+		buf.append("public class A {\n");
+		buf.append("   public String[][][] SomeMethod()\n");
+		buf.append("   {\n");
+		buf.append("		return null;\n");
+		buf.append("   }\n");
+		buf.append("}\n");
+		pack1.createCompilationUnit("A.java", buf.toString(), false, null);
+
+		buf = new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("public class B extends A {\n");
+		buf.append("   @Override\n");
+		buf.append("   public String[][][] SomeMethod()\n");
+		buf.append("   {\n");
+		buf.append("		return new String[0][][];\n");
+		buf.append("   }\n"); 
+		buf.append("}\n");
+		ICompilationUnit cu=pack1.createCompilationUnit("B.java", buf.toString(), false, null);
+
+		CompilationUnit astRoot= getASTRoot(cu);
+		ArrayList<IJavaCompletionProposal> proposals= collectCorrections(cu, astRoot);
+		assertNumberOfProposals(proposals, 2);
+		CUCorrectionProposal proposal= (CUCorrectionProposal)proposals.get(0);
+
+		assertEqualString(proposal.getDisplayString(), "Change return type of 'SomeMethod(..)' to '@NonNull'");
+
+		String preview= getPreviewContent(proposal);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.NonNull;\n");
+		buf.append("\n");
+		buf.append("public class B extends A {\n");
+		buf.append("   @Override\n");
+		buf.append("   public String @NonNull [][][] SomeMethod()\n");
+		buf.append("   {\n");
+		buf.append("		return new String[0][][];\n");
+		buf.append("   }\n"); 
+		buf.append("}\n");
+		assertEqualString(preview, buf.toString());
+	}
 }
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/QuickFixTest.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/QuickFixTest.java
index 8b8373c..4752a2a 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/QuickFixTest.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/QuickFixTest.java
@@ -107,6 +107,7 @@
 		suite.addTest(TypeParameterMismatchTest.suite());
 		suite.addTest(PropertiesFileQuickAssistTest.suite());
 		suite.addTest(NullAnnotationsQuickFixTest.suite());
+		suite.addTest(NullAnnotationsQuickFixTest18.suite());
 		suite.addTest(NullAnnotationsQuickFixTest18Mix.suite());
 		suite.addTest(AnnotateAssistTest15.suite());
 		suite.addTest(AnnotateAssistTest18.suite());
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/QuickFixTest18.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/QuickFixTest18.java
index 06bdfc3..2c90bb4 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/QuickFixTest18.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/QuickFixTest18.java
@@ -12,6 +12,7 @@
 
 import java.util.ArrayList;
 import java.util.Hashtable;
+import java.util.List;
 
 import org.eclipse.jdt.testplugin.JavaProjectHelper;
 import org.eclipse.jdt.testplugin.TestOptions;
@@ -27,6 +28,7 @@
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
 import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.compiler.IProblem;
 import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
 
@@ -1527,4 +1529,514 @@
 		buf.append("}\n");
 		assertEqualString(preview, buf.toString());
 	}
+
+	public void testBug514580_avoidRedundantNonNullInChangeMethodSignatureFix() throws Exception {
+		Hashtable<String, String> options= JavaCore.getOptions();
+		options.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+		JavaCore.setOptions(options);
+		JavaProjectHelper.addLibrary(fJProject1, new Path(Java18ProjectTestSetup.getJdtAnnotations20Path()));
+		
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+
+		StringBuffer buf;
+
+		buf= new StringBuffer();
+		buf.append("@org.eclipse.jdt.annotation.NonNullByDefault\n");
+		buf.append("package test1;\n");
+		pack1.createCompilationUnit("package-info.java", buf.toString(), false, null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.NonNull;\n");
+		buf.append("import org.eclipse.jdt.annotation.NonNullByDefault;\n");
+		buf.append("import org.eclipse.jdt.annotation.Nullable;\n");
+		buf.append("\n");
+		buf.append("@NonNullByDefault({})\n");
+		buf.append("interface I1 {\n");
+		buf.append("	void g(@NonNull Number n1, @Nullable Number n2);\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("interface I2 {\n");
+		buf.append("\n");
+		buf.append("	void h(Number n1, @Nullable Number n2);\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("class X {\n");
+		buf.append("	public int f(Boolean n1, @Nullable Boolean n2, I1 i1, I2 i2) {\n");
+		buf.append("		i1.g(n1, n2);\n");
+		buf.append("		i2.h(n1, n2);\n");
+		buf.append("	}\n");
+		buf.append("}");
+		ICompilationUnit cu= pack1.createCompilationUnit("X.java", buf.toString(), false, null);
+
+		CompilationUnit astRoot= getASTRoot(cu);
+		IProblem[] problems= astRoot.getProblems();
+		assertNumberOfProblems(2, problems);
+		List<IJavaCompletionProposal> proposals1= collectCorrections(cu, problems[0], null);
+		List<IJavaCompletionProposal> proposals2= collectCorrections(cu, problems[1], null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.NonNull;\n");
+		buf.append("import org.eclipse.jdt.annotation.NonNullByDefault;\n");
+		buf.append("import org.eclipse.jdt.annotation.Nullable;\n");
+		buf.append("\n");
+		buf.append("@NonNullByDefault({})\n");
+		buf.append("interface I1 {\n");
+		buf.append("	void g(@NonNull Boolean n1, @Nullable Boolean n2);\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("interface I2 {\n");
+		buf.append("\n");
+		buf.append("	void h(Number n1, @Nullable Number n2);\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("class X {\n");
+		buf.append("	public int f(Boolean n1, @Nullable Boolean n2, I1 i1, I2 i2) {\n");
+		buf.append("		i1.g(n1, n2);\n");
+		buf.append("		i2.h(n1, n2);\n");
+		buf.append("	}\n");
+		buf.append("}");
+		assertProposalPreviewEquals(buf.toString(), "Change method 'g(Number, Number)' to 'g(Boolean, Boolean)'", proposals1);		
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.NonNull;\n");
+		buf.append("import org.eclipse.jdt.annotation.NonNullByDefault;\n");
+		buf.append("import org.eclipse.jdt.annotation.Nullable;\n");
+		buf.append("\n");
+		buf.append("@NonNullByDefault({})\n");
+		buf.append("interface I1 {\n");
+		buf.append("	void g(@NonNull Number n1, @Nullable Number n2);\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("interface I2 {\n");
+		buf.append("\n");
+		buf.append("	void h(Boolean n1, @Nullable Boolean n2);\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("class X {\n");
+		buf.append("	public int f(Boolean n1, @Nullable Boolean n2, I1 i1, I2 i2) {\n");
+		buf.append("		i1.g(n1, n2);\n");
+		buf.append("		i2.h(n1, n2);\n");
+		buf.append("	}\n");
+		buf.append("}");
+		assertProposalPreviewEquals(buf.toString(), "Change method 'h(Number, Number)' to 'h(Boolean, Boolean)'", proposals2);		
+	}
+	public void testBug514580_avoidRedundantNonNullInTypeChange_field() throws Exception {
+		Hashtable<String, String> options= JavaCore.getOptions();
+		options.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+		JavaCore.setOptions(options);
+		JavaProjectHelper.addLibrary(fJProject1, new Path(Java18ProjectTestSetup.getJdtAnnotations20Path()));
+		
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+
+		StringBuffer buf;
+
+		buf= new StringBuffer();
+		buf.append("@org.eclipse.jdt.annotation.NonNullByDefault\n");
+		buf.append("package test1;\n");
+		pack1.createCompilationUnit("package-info.java", buf.toString(), false, null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.lang.annotation.ElementType;\n");
+		buf.append("import java.lang.annotation.Target;\n");
+		buf.append("import java.util.Map;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE})\n");
+		buf.append("@interface Pure {}\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})\n");
+		buf.append("@interface Mixed {}\n");
+		buf.append("\n");
+		buf.append("@NonNullByDefault({})\n");
+		buf.append("interface I1 {\n");
+		buf.append("	@NonNull @Mixed @Pure\n");
+		buf.append("	public String g();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("interface I2 {\n");
+		buf.append("	@Mixed @Pure\n");
+		buf.append("	public String g();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("class X {\n");
+		buf.append("	Map<? extends Number, @Nullable Integer> @Nullable [] f1;\n");
+		buf.append("	Map<? extends Number, @Nullable Integer> @Nullable [] f2;\n");
+		buf.append("\n");
+		buf.append("	public void f(I1 i1, I2 i2) {\n");
+		buf.append("		f1 = i1.g();\n");
+		buf.append("		f2 = i2.g();\n");
+		buf.append("\n");
+		buf.append("	}\n");
+		buf.append("}");
+		ICompilationUnit cu= pack1.createCompilationUnit("X.java", buf.toString(), false, null);
+
+		CompilationUnit astRoot= getASTRoot(cu);
+		IProblem[] problems= astRoot.getProblems();
+		assertNumberOfProblems(2, problems);
+		List<IJavaCompletionProposal> proposals1= collectCorrections(cu, problems[0], null);
+		List<IJavaCompletionProposal> proposals2= collectCorrections(cu, problems[1], null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.lang.annotation.ElementType;\n");
+		buf.append("import java.lang.annotation.Target;\n");
+		buf.append("import java.util.Map;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE})\n");
+		buf.append("@interface Pure {}\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})\n");
+		buf.append("@interface Mixed {}\n");
+		buf.append("\n");
+		buf.append("@NonNullByDefault({})\n");
+		buf.append("interface I1 {\n");
+		buf.append("	@NonNull @Mixed @Pure\n");
+		buf.append("	public String g();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("interface I2 {\n");
+		buf.append("	@Mixed @Pure\n");
+		buf.append("	public String g();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("class X {\n");
+		buf.append("	@Mixed @Pure String f1;\n");
+		buf.append("	Map<? extends Number, @Nullable Integer> @Nullable [] f2;\n");
+		buf.append("\n");
+		buf.append("	public void f(I1 i1, I2 i2) {\n");
+		buf.append("		f1 = i1.g();\n");
+		buf.append("		f2 = i2.g();\n");
+		buf.append("\n");
+		buf.append("	}\n");
+		buf.append("}");
+		assertProposalPreviewEquals(buf.toString(), "Change type of 'f1' to 'String'", proposals1);		
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.lang.annotation.ElementType;\n");
+		buf.append("import java.lang.annotation.Target;\n");
+		buf.append("import java.util.Map;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE})\n");
+		buf.append("@interface Pure {}\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})\n");
+		buf.append("@interface Mixed {}\n");
+		buf.append("\n");
+		buf.append("@NonNullByDefault({})\n");
+		buf.append("interface I1 {\n");
+		buf.append("	@NonNull @Mixed @Pure\n");
+		buf.append("	public String g();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("interface I2 {\n");
+		buf.append("	@Mixed @Pure\n");
+		buf.append("	public String g();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("class X {\n");
+		buf.append("	Map<? extends Number, @Nullable Integer> @Nullable [] f1;\n");
+		buf.append("	@Mixed @Pure String f2;\n");
+		buf.append("\n");
+		buf.append("	public void f(I1 i1, I2 i2) {\n");
+		buf.append("		f1 = i1.g();\n");
+		buf.append("		f2 = i2.g();\n");
+		buf.append("\n");
+		buf.append("	}\n");
+		buf.append("}");
+		assertProposalPreviewEquals(buf.toString(), "Change type of 'f2' to 'String'", proposals2);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.lang.annotation.ElementType;\n");
+		buf.append("import java.lang.annotation.Target;\n");
+		buf.append("import java.util.Map;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE})\n");
+		buf.append("@interface Pure {}\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})\n");
+		buf.append("@interface Mixed {}\n");
+		buf.append("\n");
+		buf.append("@NonNullByDefault({})\n");
+		buf.append("interface I1 {\n");
+		buf.append("	@Mixed public Map<? extends @NonNull Number, @Nullable Integer> @Nullable [] g();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("interface I2 {\n");
+		buf.append("	@Mixed @Pure\n");
+		buf.append("	public String g();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("class X {\n");
+		buf.append("	Map<? extends Number, @Nullable Integer> @Nullable [] f1;\n");
+		buf.append("	Map<? extends Number, @Nullable Integer> @Nullable [] f2;\n");
+		buf.append("\n");
+		buf.append("	public void f(I1 i1, I2 i2) {\n");
+		buf.append("		f1 = i1.g();\n");
+		buf.append("		f2 = i2.g();\n");
+		buf.append("\n");
+		buf.append("	}\n");
+		buf.append("}");
+		assertProposalPreviewEquals(buf.toString(), "Change return type of 'g(..)' to 'Map<? extends Number, Integer>[]'", proposals1);		
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.lang.annotation.ElementType;\n");
+		buf.append("import java.lang.annotation.Target;\n");
+		buf.append("import java.util.Map;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE})\n");
+		buf.append("@interface Pure {}\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})\n");
+		buf.append("@interface Mixed {}\n");
+		buf.append("\n");
+		buf.append("@NonNullByDefault({})\n");
+		buf.append("interface I1 {\n");
+		buf.append("	@NonNull @Mixed @Pure\n");
+		buf.append("	public String g();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("interface I2 {\n");
+		buf.append("	@Mixed public Map<? extends Number, @Nullable Integer> @Nullable [] g();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("class X {\n");
+		buf.append("	Map<? extends Number, @Nullable Integer> @Nullable [] f1;\n");
+		buf.append("	Map<? extends Number, @Nullable Integer> @Nullable [] f2;\n");
+		buf.append("\n");
+		buf.append("	public void f(I1 i1, I2 i2) {\n");
+		buf.append("		f1 = i1.g();\n");
+		buf.append("		f2 = i2.g();\n");
+		buf.append("\n");
+		buf.append("	}\n");
+		buf.append("}");
+		assertProposalPreviewEquals(buf.toString(), "Change return type of 'g(..)' to 'Map<? extends Number, Integer>[]'", proposals2);		
+	}
+	public void testBug514580_avoidRedundantNonNullInTypeChange_local() throws Exception {
+		Hashtable<String, String> options= JavaCore.getOptions();
+		options.put(JavaCore.COMPILER_ANNOTATION_NULL_ANALYSIS, JavaCore.ENABLED);
+		JavaCore.setOptions(options);
+		JavaProjectHelper.addLibrary(fJProject1, new Path(Java18ProjectTestSetup.getJdtAnnotations20Path()));
+		
+		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+
+		StringBuffer buf;
+
+		buf= new StringBuffer();
+		buf.append("@org.eclipse.jdt.annotation.NonNullByDefault\n");
+		buf.append("package test1;\n");
+		pack1.createCompilationUnit("package-info.java", buf.toString(), false, null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.lang.annotation.ElementType;\n");
+		buf.append("import java.lang.annotation.Target;\n");
+		buf.append("import java.util.Map;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE})\n");
+		buf.append("@interface Pure {}\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})\n");
+		buf.append("@interface Mixed {}\n");
+		buf.append("\n");
+		buf.append("@NonNullByDefault({})\n");
+		buf.append("interface I1 {\n");
+		buf.append("	@Nullable @Mixed @Pure\n");
+		buf.append("	abstract String h();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("interface I2 {\n");
+		buf.append("	@Nullable @Mixed @Pure\n");
+		buf.append("	abstract String h();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("class X {\n");
+		buf.append("	public void f(I1 i1, I2 i2) {\n");
+		buf.append("		Map<? extends Number, @Nullable Integer>[] l1;\n");
+		buf.append("		Map<? extends Number, @Nullable Integer>[] l2;\n");
+		buf.append("		l1 = i1.h();\n");
+		buf.append("		l2 = i2.h();\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		buf.append("");
+		ICompilationUnit cu= pack1.createCompilationUnit("X.java", buf.toString(), false, null);
+
+		CompilationUnit astRoot= getASTRoot(cu);
+		IProblem[] problems= astRoot.getProblems();
+		assertNumberOfProblems(2, problems);
+		List<IJavaCompletionProposal> proposals1= collectCorrections(cu, problems[0], null);
+		List<IJavaCompletionProposal> proposals2= collectCorrections(cu, problems[1], null);
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.lang.annotation.ElementType;\n");
+		buf.append("import java.lang.annotation.Target;\n");
+		buf.append("import java.util.Map;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE})\n");
+		buf.append("@interface Pure {}\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})\n");
+		buf.append("@interface Mixed {}\n");
+		buf.append("\n");
+		buf.append("@NonNullByDefault({})\n");
+		buf.append("interface I1 {\n");
+		buf.append("	@Nullable @Mixed @Pure\n");
+		buf.append("	abstract String h();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("interface I2 {\n");
+		buf.append("	@Nullable @Mixed @Pure\n");
+		buf.append("	abstract String h();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("class X {\n");
+		buf.append("	public void f(I1 i1, I2 i2) {\n");
+		buf.append("		@Mixed @Pure String l1;\n");
+		buf.append("		Map<? extends Number, @Nullable Integer>[] l2;\n");
+		buf.append("		l1 = i1.h();\n");
+		buf.append("		l2 = i2.h();\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		buf.append("");
+		assertProposalPreviewEquals(buf.toString(), "Change type of 'l1' to 'String'", proposals1);		
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.lang.annotation.ElementType;\n");
+		buf.append("import java.lang.annotation.Target;\n");
+		buf.append("import java.util.Map;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE})\n");
+		buf.append("@interface Pure {}\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})\n");
+		buf.append("@interface Mixed {}\n");
+		buf.append("\n");
+		buf.append("@NonNullByDefault({})\n");
+		buf.append("interface I1 {\n");
+		buf.append("	@Nullable @Mixed @Pure\n");
+		buf.append("	abstract String h();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("interface I2 {\n");
+		buf.append("	@Nullable @Mixed @Pure\n");
+		buf.append("	abstract String h();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("class X {\n");
+		buf.append("	public void f(I1 i1, I2 i2) {\n");
+		buf.append("		Map<? extends Number, @Nullable Integer>[] l1;\n");
+		buf.append("		@Mixed @Pure String l2;\n");
+		buf.append("		l1 = i1.h();\n");
+		buf.append("		l2 = i2.h();\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		buf.append("");
+		assertProposalPreviewEquals(buf.toString(), "Change type of 'l2' to 'String'", proposals2);		
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.lang.annotation.ElementType;\n");
+		buf.append("import java.lang.annotation.Target;\n");
+		buf.append("import java.util.Map;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE})\n");
+		buf.append("@interface Pure {}\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})\n");
+		buf.append("@interface Mixed {}\n");
+		buf.append("\n");
+		buf.append("@NonNullByDefault({})\n");
+		buf.append("interface I1 {\n");
+		buf.append("	@Mixed abstract Map<? extends @NonNull Number, @Nullable Integer>[] h();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("interface I2 {\n");
+		buf.append("	@Nullable @Mixed @Pure\n");
+		buf.append("	abstract String h();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("class X {\n");
+		buf.append("	public void f(I1 i1, I2 i2) {\n");
+		buf.append("		Map<? extends Number, @Nullable Integer>[] l1;\n");
+		buf.append("		Map<? extends Number, @Nullable Integer>[] l2;\n");
+		buf.append("		l1 = i1.h();\n");
+		buf.append("		l2 = i2.h();\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		buf.append("");
+		assertProposalPreviewEquals(buf.toString(), "Change return type of 'h(..)' to 'Map<? extends Number, Integer>[]'", proposals1);		
+
+		buf= new StringBuffer();
+		buf.append("package test1;\n");
+		buf.append("\n");
+		buf.append("import java.lang.annotation.ElementType;\n");
+		buf.append("import java.lang.annotation.Target;\n");
+		buf.append("import java.util.Map;\n");
+		buf.append("\n");
+		buf.append("import org.eclipse.jdt.annotation.*;\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE})\n");
+		buf.append("@interface Pure {}\n");
+		buf.append("\n");
+		buf.append("@Target({ElementType.TYPE_USE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})\n");
+		buf.append("@interface Mixed {}\n");
+		buf.append("\n");
+		buf.append("@NonNullByDefault({})\n");
+		buf.append("interface I1 {\n");
+		buf.append("	@Nullable @Mixed @Pure\n");
+		buf.append("	abstract String h();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("interface I2 {\n");
+		buf.append("	@Mixed abstract Map<? extends Number, @Nullable Integer>[] h();\n");
+		buf.append("}\n");
+		buf.append("\n");
+		buf.append("class X {\n");
+		buf.append("	public void f(I1 i1, I2 i2) {\n");
+		buf.append("		Map<? extends Number, @Nullable Integer>[] l1;\n");
+		buf.append("		Map<? extends Number, @Nullable Integer>[] l2;\n");
+		buf.append("		l1 = i1.h();\n");
+		buf.append("		l2 = i2.h();\n");
+		buf.append("	}\n");
+		buf.append("}\n");
+		buf.append("");
+		assertProposalPreviewEquals(buf.toString(), "Change return type of 'h(..)' to 'Map<? extends Number, Integer>[]'", proposals2);		
+	}
 }
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/codemanipulation/StubUtility2.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/codemanipulation/StubUtility2.java
index 2c977a1..fe8a80f 100644
--- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/codemanipulation/StubUtility2.java
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/codemanipulation/StubUtility2.java
@@ -372,10 +372,7 @@
 		decl.setConstructor(false);
 		
 		ITypeBinding bindingReturnType= binding.getReturnType();
-		if (bindingReturnType.isWildcardType()) {
-			ITypeBinding bound= bindingReturnType.getBound();
-			bindingReturnType= (bound != null) ? bound : bindingReturnType.getErasure();
-		}
+		bindingReturnType = StubUtility2.replaceWildcardsAndCaptures(bindingReturnType);
 		
 		if (JavaModelUtil.is50OrHigher(javaProject)) {
 			createTypeParameters(imports, context, ast, binding, decl);
@@ -498,10 +495,7 @@
 		for (int i= 0; i < params.length; i++) {
 			SingleVariableDeclaration var= ast.newSingleVariableDeclaration();
 			ITypeBinding type= params[i];
-			if (type.isWildcardType()) {
-				ITypeBinding bound= type.getBound();
-				type= (bound != null) ? bound : type.getErasure();
-			}
+			type=replaceWildcardsAndCaptures(type);
 			if (!is50OrHigher) {
 				type= type.getErasure();
 				var.setType(imports.addImport(type, ast, context, TypeLocation.PARAMETER));
@@ -1008,4 +1002,12 @@
 		}
 		return null;
 	}
+
+	public static ITypeBinding replaceWildcardsAndCaptures(ITypeBinding type) {
+		while (type.isWildcardType() || type.isCapture() || (type.isArray() && type.getElementType().isCapture())) {
+			ITypeBinding bound= type.getBound();
+			type= (bound != null) ? bound : type.getErasure();
+		}
+		return type;
+	}
 }
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/dom/ASTNodeFactory.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/dom/ASTNodeFactory.java
index fba38d7..1ff93e8 100644
--- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/dom/ASTNodeFactory.java
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/dom/ASTNodeFactory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2014 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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 @@
 import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.ASTParser;
 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
+import org.eclipse.jdt.core.dom.AnnotatableType;
 import org.eclipse.jdt.core.dom.ArrayType;
 import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jdt.core.dom.Dimension;
@@ -43,7 +44,9 @@
 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
+import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.TypeLocation;
 
+import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2;
 import org.eclipse.jdt.internal.corext.util.JDTUIHelperClasses;
 
 /**
@@ -354,36 +357,29 @@
 		return result;
 	}
 
+	/**
+	 * Create a Type suitable as the creationType in a ClassInstanceCreation expression.
+	 * @param ast The AST to create the nodes for.
+	 * @param typeBinding binding representing the given class type
+	 * @param importRewrite the import rewrite to use
+	 * @param importContext the import context used to determine which (null) annotations to consider
+	 * @return a Type suitable as the creationType in a ClassInstanceCreation expression.
+	 */
 	public static Type newCreationType(AST ast, ITypeBinding typeBinding, ImportRewrite importRewrite, ImportRewriteContext importContext) {
 		if (typeBinding.isParameterizedType()) {
 			Type baseType= newCreationType(ast, typeBinding.getTypeDeclaration(), importRewrite, importContext);
+			IAnnotationBinding[] typeAnnotations= importContext.removeRedundantTypeAnnotations(typeBinding.getTypeAnnotations(), TypeLocation.NEW, typeBinding);
+			for (IAnnotationBinding typeAnnotation : typeAnnotations) {
+				((AnnotatableType)baseType).annotations().add(importRewrite.addAnnotation(typeAnnotation, ast, importContext));
+			}
 			ParameterizedType parameterizedType= ast.newParameterizedType(baseType);
 			for (ITypeBinding typeArgument : typeBinding.getTypeArguments()) {
-				parameterizedType.typeArguments().add(newCreationType(ast, typeArgument, importRewrite, importContext));
+				typeArgument= StubUtility2.replaceWildcardsAndCaptures(typeArgument);
+				parameterizedType.typeArguments().add(importRewrite.addImport(typeArgument, ast, importContext, TypeLocation.TYPE_ARGUMENT));
 			}
 			return parameterizedType;
-			
-		} else if (typeBinding.isParameterizedType()) {
-			Type elementType= newCreationType(ast, typeBinding.getElementType(), importRewrite, importContext);
-			ArrayType arrayType= ast.newArrayType(elementType, 0);
-			while (typeBinding.isArray()) {
-				Dimension dimension= ast.newDimension();
-				IAnnotationBinding[] typeAnnotations= typeBinding.getTypeAnnotations();
-				for (IAnnotationBinding typeAnnotation : typeAnnotations) {
-					dimension.annotations().add(importRewrite.addAnnotation(typeAnnotation, ast, importContext));
-				}
-				arrayType.dimensions().add(dimension);
-				typeBinding= typeBinding.getComponentType();
-			}
-			return arrayType;
-				
-		} else if (typeBinding.isWildcardType()) {
-			ITypeBinding bound= typeBinding.getBound();
-			typeBinding= (bound != null) ? bound : typeBinding.getErasure();
-			return newCreationType(ast, typeBinding, importRewrite, importContext);
-			
 		} else {
-			return importRewrite.addImport(typeBinding, ast, importContext);
+			return importRewrite.addImport(typeBinding, ast, importContext, TypeLocation.NEW);
 		}
 	}
 }
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/dom/TypeAnnotationRewrite.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/dom/TypeAnnotationRewrite.java
new file mode 100644
index 0000000..d2f5271
--- /dev/null
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/dom/TypeAnnotationRewrite.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Till Brychcy 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:
+ *     Till Brychcy - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.corext.dom;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import java.util.List;
+
+import org.eclipse.text.edits.TextEditGroup;
+
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.IAnnotationBinding;
+import org.eclipse.jdt.core.dom.IMemberValuePairBinding;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
+import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
+
+import org.eclipse.jdt.internal.corext.util.JDTUIHelperClasses;
+import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
+
+/**
+ * Rewrite helper for type annotations.
+ * 
+ * @see JDTUIHelperClasses
+ * @since 3.13
+ */
+public class TypeAnnotationRewrite {
+
+	/**
+	 * Removes all {@link Annotation} whose only {@link Target} is {@link ElementType#TYPE_USE} from
+	 * <code>node</code>'s <code>childListProperty</code>.
+	 * <p>
+	 * In a combination of {@link ElementType#TYPE_USE} and {@link ElementType#TYPE_PARAMETER}
+	 * the latter is ignored, because this is implied by the former and creates no ambiguity.</p>
+	 * 
+	 * @param node ASTNode
+	 * @param childListProperty child list property
+	 * @param rewrite rewrite that removes the nodes
+	 * @param editGroup the edit group in which to collect the corresponding text edits, or null if
+	 *            ungrouped
+	 */
+	public static void removePureTypeAnnotations(ASTNode node, ChildListPropertyDescriptor childListProperty, ASTRewrite rewrite, TextEditGroup editGroup) {
+		CompilationUnit root= (CompilationUnit) node.getRoot();
+		if (!JavaModelUtil.is18OrHigher(root.getJavaElement().getJavaProject())) {
+			return;
+		}
+		ListRewrite listRewrite= rewrite.getListRewrite(node, childListProperty);
+		@SuppressWarnings("unchecked")
+		List<? extends ASTNode> children= (List<? extends ASTNode>) node.getStructuralProperty(childListProperty);
+		for (ASTNode child : children) {
+			if (child instanceof Annotation) {
+				Annotation annotation= (Annotation) child;
+				if (isPureTypeAnnotation(annotation)) {
+					listRewrite.remove(child, editGroup);
+				}
+			}
+		}
+	}
+
+	private static boolean isPureTypeAnnotation(Annotation annotation) {
+		IAnnotationBinding binding= annotation.resolveAnnotationBinding();
+		if (binding == null) {
+			return false;
+		}
+		IAnnotationBinding targetAnnotationBinding= findTargetAnnotation(binding.getAnnotationType().getAnnotations());
+
+		if (targetAnnotationBinding == null) {
+			return false;
+		}
+		return isTypeUseOnly(targetAnnotationBinding);
+	}
+
+	private static IAnnotationBinding findTargetAnnotation(IAnnotationBinding[] metaAnnotations) {
+		for (int i= 0; i < metaAnnotations.length; i++) {
+			IAnnotationBinding binding= metaAnnotations[i];
+			ITypeBinding annotationType= binding.getAnnotationType();
+			if (annotationType != null && annotationType.getQualifiedName().equals(Target.class.getName())) {
+				return binding;
+			}
+		}
+		return null;
+	}
+
+	private static boolean isTypeUseOnly(IAnnotationBinding binding) {
+		IMemberValuePairBinding[] pairs= binding.getAllMemberValuePairs();
+		boolean typeUseSeen= false;
+		boolean otherSeen= false;
+		for (final IMemberValuePairBinding pair : pairs) {
+			if (pair.getKey() == null || pair.getKey().equals("value")) { //$NON-NLS-1$
+				Object value= pair.getValue();
+				if (value instanceof Object[]) {
+					Object[] values= (Object[]) value;
+					for (int k= 0; k < values.length; k++) {
+						if (values[k] instanceof IVariableBinding) {
+							String name= ((IVariableBinding) values[k]).getName();
+							if (name.equals(ElementType.TYPE_USE.name())) {
+								typeUseSeen= true;
+							} else if (!name.equals(ElementType.TYPE_PARAMETER.name())) {
+								otherSeen= true;
+							}
+						}
+					}
+				} else if (value instanceof IVariableBinding) {
+					String name= ((IVariableBinding) value).getName();
+					if (name.equals(ElementType.TYPE_USE.name())) {
+						typeUseSeen= true;
+					} else if (!name.equals(ElementType.TYPE_PARAMETER.name())) {
+						otherSeen= true;
+					}
+				}
+			}
+		}
+		return typeUseSeen && !otherSeen;
+	}
+}
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/ExternalNullAnnotationChangeProposals.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/ExternalNullAnnotationChangeProposals.java
index ba9b374..8ea1991 100644
--- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/ExternalNullAnnotationChangeProposals.java
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/fix/ExternalNullAnnotationChangeProposals.java
@@ -360,7 +360,8 @@
 		int extraDims= 0; // total number of extra dimensions
 		int outerExtraDims= 0; // number of outer extra dimension preceding the annotation position
 
-		if (coveringNode instanceof Dimension && coveringNode.getLocationInParent() == SingleVariableDeclaration.EXTRA_DIMENSIONS2_PROPERTY) {
+		boolean coversDimension= coveringNode instanceof Dimension;
+		if (coversDimension && coveringNode.getLocationInParent() == SingleVariableDeclaration.EXTRA_DIMENSIONS2_PROPERTY) {
 			// annotating extra dimensions, remember dimension counts
 			variable= (SingleVariableDeclaration) coveringNode.getParent();
 			outer= variable.getType();
@@ -368,6 +369,14 @@
 			List<?> extraDimensions= variable.extraDimensions();
 			extraDims= extraDimensions.size();
 			outerExtraDims= extraDimensions.indexOf(coveringNode);
+		} else if (coversDimension && coveringNode.getLocationInParent() == MethodDeclaration.EXTRA_DIMENSIONS2_PROPERTY) {
+			// annotating extra dimensions, remember dimension counts
+			MethodDeclaration method= (MethodDeclaration) coveringNode.getParent();
+			outer= method.getReturnType2();
+			inner= method.getReturnType2();
+			List<?> extraDimensions= method.extraDimensions();
+			extraDims= extraDimensions.size();
+			outerExtraDims= extraDimensions.indexOf(coveringNode);
 		} else if (coveringNode instanceof SingleVariableDeclaration) {
 			// annotating varargs ellipsis?
 			variable= (SingleVariableDeclaration) coveringNode;
@@ -423,11 +432,11 @@
 				rendererNullable.addDimension(annotateVarargs);
 				rendererRemove.addDimension(annotateVarargs);
 			}
-			for (int i= 0; i < extraDims; i++) {
-				rendererNonNull.addDimension(i == outerExtraDims);
-				rendererNullable.addDimension(i == outerExtraDims);
-				rendererRemove.addDimension(i == outerExtraDims);
-			}
+		}
+		for (int i= 0; i < extraDims; i++) {
+			rendererNonNull.addDimension(i == outerExtraDims);
+			rendererNullable.addDimension(i == outerExtraDims);
+			rendererRemove.addDimension(i == outerExtraDims);
 		}
 		boolean useJava8= JavaModelUtil.is18OrHigher(javaProject.getOption(JavaCore.COMPILER_SOURCE, true));
 		if (!useJava8 && (outer != inner || outerExtraDims > 0)) { // below 1.8 we can only annotate the top type (not type parameter)
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 eb9e6eb..39103e6 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
@@ -32,7 +32,10 @@
 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;
@@ -49,6 +52,7 @@
 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;
@@ -117,7 +121,22 @@
 			return fUnit;
 		}
 
-		boolean checkExisting(List<IExtendedModifier> existingModifiers, ListRewrite listRewrite, TextEditGroup editGroup) {
+		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;
@@ -267,9 +286,10 @@
 		@Override
 		public void rewriteAST(CompilationUnitRewrite cuRewrite, LinkedProposalModel model) throws CoreException {
 			AST ast= cuRewrite.getRoot().getAST();
-			ListRewrite listRewrite= cuRewrite.getASTRewrite().getListRewrite(fBodyDeclaration, fBodyDeclaration.getModifiersProperty());
+			ListRewrite listRewrite= getAnnotationListRewrite(fBodyDeclaration.getReturnType2(), cuRewrite,
+										fBodyDeclaration, fBodyDeclaration.getModifiersProperty());
 			TextEditGroup group= createTextEditGroup(fMessage, cuRewrite);
-			if (!checkExisting(fBodyDeclaration.modifiers(), listRewrite, group))
+			if (!checkExisting(listRewrite, group))
 				return;
 			if (!fRequireExplicitAnnotation) {
 				if (fUseNullTypeAnnotations
@@ -331,9 +351,9 @@
 		@Override
 		public void rewriteAST(CompilationUnitRewrite cuRewrite, LinkedProposalModel linkedModel) throws CoreException {
 			AST ast= cuRewrite.getRoot().getAST();
-			ListRewrite listRewrite= cuRewrite.getASTRewrite().getListRewrite(fArgument, SingleVariableDeclaration.MODIFIERS2_PROPERTY);
+			ListRewrite listRewrite= getAnnotationListRewrite(fArgument.getType(), cuRewrite, fArgument, SingleVariableDeclaration.MODIFIERS2_PROPERTY);
 			TextEditGroup group= createTextEditGroup(fMessage, cuRewrite);
-			if (!checkExisting(fArgument.modifiers(), listRewrite, group))
+			if (!checkExisting(listRewrite, group))
 				return;
 			if (!fRequireExplicitAnnotation) {
 				if (fUseNullTypeAnnotations
@@ -594,6 +614,7 @@
 					case IProblem.RequiredNonNullButProvidedUnknown:
 					case IProblem.ConflictingNullAnnotations:
 					case IProblem.ConflictingInheritedNullAnnotations:
+					case IProblem.RedundantNullCheckAgainstNonNullType:
 						if (fAffectsParameter) {
 							// statement suggests changing parameters:
 							if (selectedNode instanceof SimpleName) {
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/util/JDTUIHelperClasses.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/util/JDTUIHelperClasses.java
index f53778d..262de59 100644
--- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/util/JDTUIHelperClasses.java
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/util/JDTUIHelperClasses.java
@@ -28,6 +28,7 @@
 import org.eclipse.jdt.internal.corext.dom.NecessaryParenthesesChecker;
 import org.eclipse.jdt.internal.corext.dom.ReplaceRewrite;
 import org.eclipse.jdt.internal.corext.dom.StatementRewrite;
+import org.eclipse.jdt.internal.corext.dom.TypeAnnotationRewrite;
 import org.eclipse.jdt.internal.corext.dom.TypeRules;
 import org.eclipse.jdt.internal.corext.dom.VariableDeclarationRewrite;
 import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
@@ -121,6 +122,7 @@
  * <li>{@link ModifierRewrite}</li>
  * <li>{@link ReplaceRewrite}</li>
  * <li>{@link StatementRewrite}</li>
+ * <li>{@link TypeAnnotationRewrite}</li>
  * <li>{@link VariableDeclarationRewrite}</li>
  * </ul>
  * 
diff --git a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodAnalyzer.java b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodAnalyzer.java
index 35731af..79aaa69 100644
--- a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodAnalyzer.java
+++ b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodAnalyzer.java
@@ -56,6 +56,7 @@
 import org.eclipse.jdt.core.dom.Message;
 import org.eclipse.jdt.core.dom.MethodDeclaration;
 import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jdt.core.dom.NodeFinder;
 import org.eclipse.jdt.core.dom.PrimitiveType;
 import org.eclipse.jdt.core.dom.QualifiedName;
 import org.eclipse.jdt.core.dom.SimpleName;
@@ -77,6 +78,8 @@
 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.TypeLocation;
 
+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.ContextSensitiveImportRewriteContext;
 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
@@ -97,8 +100,6 @@
 
 import org.eclipse.jdt.ui.JavaElementLabels;
 
-import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
-import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
 import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
 
 /* package */ class ExtractMethodAnalyzer extends CodeAnalyzer {
@@ -794,7 +795,26 @@
 					}
 					if (name.resolveBinding() instanceof IVariableBinding) {
 						StructuralPropertyDescriptor locationInParent= name.getLocationInParent();
-						if (locationInParent == QualifiedName.NAME_PROPERTY || (locationInParent == FieldAccess.NAME_PROPERTY && !(((FieldAccess) name.getParent()).getExpression() instanceof ThisExpression)))  {
+						boolean isPartOfQualifiedName= false;
+						boolean isPartOfQualifier= false;
+						if (locationInParent == QualifiedName.NAME_PROPERTY) {
+							isPartOfQualifiedName= true;
+							QualifiedName qualifiedName= (QualifiedName) name.getParent();
+							QualifiedName currParent= qualifiedName;
+							while (true) {
+								ASTNode parent= currParent.getParent();
+								if (parent instanceof QualifiedName) {
+									currParent= (QualifiedName) parent;
+								} else {
+									break;
+								}
+							}
+							if (!qualifiedName.equals(currParent)) {
+								isPartOfQualifier= true;
+							}
+						}
+						if ((isPartOfQualifiedName && !isPartOfQualifier)
+								|| (locationInParent == FieldAccess.NAME_PROPERTY && !(((FieldAccess) name.getParent()).getExpression() instanceof ThisExpression))) {
 							status.addFatalError(RefactoringCoreMessages.ExtractMethodAnalyzer_cannot_extract_part_of_qualified_name);
 							break superCall;
 						}
@@ -827,7 +847,9 @@
 	@Override
 	public boolean visit(Assignment node) {
 		boolean result= super.visit(node);
-		if ((getSelection().covers(node.getLeftHandSide()) && !getSelection().covers(node.getRightHandSide())) || getSelection().coveredBy(node.getLeftHandSide())) {
+		Selection selection= getSelection();
+		ASTNode selectedNode= NodeFinder.perform(node, selection.getOffset(), selection.getLength());
+		if ((selectedNode != null && SnippetFinder.isLeftHandSideOfAssignment(selectedNode)) || (selection.covers(node.getLeftHandSide()) && !selection.covers(node.getRightHandSide()))) {
 			invalidSelection(
 				RefactoringCoreMessages.ExtractMethodAnalyzer_leftHandSideOfAssignment,
 				JavaStatusContext.create(fCUnit, node));
diff --git a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodRefactoring.java b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodRefactoring.java
index 0ffd8b2..1be1ae7 100644
--- a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodRefactoring.java
+++ b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodRefactoring.java
@@ -83,6 +83,7 @@
 import org.eclipse.jdt.core.dom.SimpleName;
 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
 import org.eclipse.jdt.core.dom.Statement;
+import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
 import org.eclipse.jdt.core.dom.ThisExpression;
 import org.eclipse.jdt.core.dom.Type;
 import org.eclipse.jdt.core.dom.TypeDeclaration;
@@ -101,6 +102,8 @@
 import org.eclipse.jdt.core.refactoring.descriptors.ExtractMethodDescriptor;
 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
 
+import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
+import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
 import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
 import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
@@ -119,6 +122,7 @@
 import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
 import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo;
 import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
+import org.eclipse.jdt.internal.corext.refactoring.code.SnippetFinder.Match;
 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
 import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
 import org.eclipse.jdt.internal.corext.refactoring.util.SelectionAwareSourceRangeComputer;
@@ -129,9 +133,6 @@
 import org.eclipse.jdt.ui.JavaElementLabels;
 
 import org.eclipse.jdt.internal.ui.text.correction.ModifierCorrectionSubProcessor;
-
-import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
-import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
 import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
 
 /**
@@ -160,7 +161,7 @@
 	private Set<String> fUsedNames;
 	private boolean fGenerateJavadoc;
 	private boolean fReplaceDuplicates;
-	private SnippetFinder.Match[] fDuplicates;
+	private List<SnippetFinder.Match> fDuplicates;
 	private int fDestinationIndex= 0;
 	// either of type TypeDeclaration or AnonymousClassDeclaration
 	private ASTNode fDestination;
@@ -715,8 +716,8 @@
 		if (fDuplicates == null)
 			return 0;
 		int result=0;
-		for (int i= 0; i < fDuplicates.length; i++) {
-			if (!fDuplicates[i].isInvalidNode())
+		for (Match duplicate : fDuplicates) {
+			if (!duplicate.isInvalidNode())
 				result++;
 		}
 		return result;
@@ -783,8 +784,116 @@
 			start= start.getParent();
 		}
 
-		fDuplicates= SnippetFinder.perform(start, fAnalyzer.getSelectedNodes());
-		fReplaceDuplicates= fDuplicates.length > 0 && ! fAnalyzer.isLiteralNodeSelected();
+		fDuplicates= findValidDuplicates(start);
+		fReplaceDuplicates= fDuplicates.size() > 0 && !fAnalyzer.isLiteralNodeSelected();
+	}
+
+	private List<SnippetFinder.Match> findValidDuplicates(ASTNode startNode) {
+		List<Match> duplicates= SnippetFinder.perform(startNode, fAnalyzer.getSelectedNodes());
+		List<SnippetFinder.Match> validDuplicates= new ArrayList<>();
+
+		for (Match duplicate : duplicates) {
+			if (duplicate != null && !duplicate.isInvalidNode()) {
+				try {
+					ASTNode[] nodes= duplicate.getNodes();
+					int duplicateStart= nodes[0].getStartPosition();
+					ASTNode lastNode= nodes[nodes.length - 1];
+					int duplicateEnd= lastNode.getStartPosition() + lastNode.getLength();
+					int duplicateLength= duplicateEnd - duplicateStart;
+					ExtractMethodAnalyzer analyzer= new ExtractMethodAnalyzer(fCUnit, Selection.createFromStartLength(duplicateStart, duplicateLength));
+					fRoot.accept(analyzer);
+					RefactoringStatus result= new RefactoringStatus();
+					result.merge(analyzer.checkInitialConditions(fImportRewriter));
+
+					if (!result.hasFatalError()) {
+						ITypeBinding originalReturnTypeBinding= fAnalyzer.getReturnTypeBinding();
+						ITypeBinding duplicateReturnTypeBinding= analyzer.getReturnTypeBinding();
+
+						if (originalReturnTypeBinding == null && duplicateReturnTypeBinding == null) {
+							validDuplicates.add(duplicate);
+						} else if (originalReturnTypeBinding != null && duplicateReturnTypeBinding != null) {
+							if (!originalReturnTypeBinding.equals(duplicateReturnTypeBinding)) {
+								if (duplicateReturnTypeBinding.equals(startNode.getAST().resolveWellKnownType("void"))) { //$NON-NLS-1$
+									// extracted snippet returns non-void and duplicate snippet returns void => OK 
+									validDuplicates.add(duplicate);
+								}
+							} else {
+								IVariableBinding originalReturnValBinding= fAnalyzer.getReturnValue();
+								IVariableBinding duplicateReturnValBinding= analyzer.getReturnValue();
+
+								if (originalReturnValBinding == null && duplicateReturnValBinding == null) {
+									validDuplicates.add(duplicate);
+								} else if (originalReturnValBinding != null && duplicateReturnValBinding != null) {
+									BodyDeclaration originalEnclosingBodyDeclaration= fAnalyzer.getEnclosingBodyDeclaration();
+									BodyDeclaration duplicateEnclosingBodyDeclaration= analyzer.getEnclosingBodyDeclaration();
+									VariableDeclaration originalReturnNode= ASTNodes.findVariableDeclaration(originalReturnValBinding, originalEnclosingBodyDeclaration);
+									VariableDeclaration duplicateReturnNode= ASTNodes.findVariableDeclaration(duplicateReturnValBinding, duplicateEnclosingBodyDeclaration);
+
+									if (originalReturnNode != null && duplicateReturnNode != null) {
+										boolean matches;
+										if (!fAnalyzer.getSelection().covers(originalReturnNode) && !analyzer.getSelection().covers(duplicateReturnNode)) {
+											// returned variables are defined outside of the selection => always OK
+											matches= true;
+										} else {
+											matches= matchesLocationInEnclosingBodyDecl(originalEnclosingBodyDeclaration, duplicateEnclosingBodyDeclaration, originalReturnNode, duplicateReturnNode);
+										}
+										
+										if (matches) {
+											validDuplicates.add(duplicate);
+										}
+									}
+								}
+							}
+						}
+					}
+				} catch (CoreException e) {
+					// consider as invalid duplicate
+				}
+			}
+		}
+		return validDuplicates;
+	}
+
+	private boolean matchesLocationInEnclosingBodyDecl(BodyDeclaration originalEnclosingBodyDeclaration, BodyDeclaration duplicateEnclosingBodyDeclaration,
+			VariableDeclaration originalReturnNode, VariableDeclaration duplicateReturnNode) {
+		boolean matches= true;
+		ASTNode original= originalReturnNode;
+		ASTNode dupliacte= duplicateReturnNode;
+
+		// walk up the parent chains to check if the location of the return nodes in their respective parent chains is same
+		do {
+			ASTNode originalParent= original.getParent();
+			ASTNode duplicateParent= dupliacte.getParent();
+			StructuralPropertyDescriptor originalLoc= original.getLocationInParent();
+			StructuralPropertyDescriptor duplicateLoc= dupliacte.getLocationInParent();
+
+			if (originalParent != null && duplicateParent != null
+					&& originalLoc.getNodeClass().equals(duplicateLoc.getNodeClass())
+					&& originalLoc.getId().equals(duplicateLoc.getId())) {
+				if (originalLoc.isChildListProperty() && duplicateLoc.isChildListProperty()) {
+					int indexOfOriginal= ((List<?>) originalParent.getStructuralProperty(originalLoc)).indexOf(original);
+					int indexOfDuplicate= ((List<?>) duplicateParent.getStructuralProperty(duplicateLoc)).indexOf(dupliacte);
+					if (indexOfOriginal != indexOfDuplicate) {
+						matches= false;
+						break;
+					}
+				}
+			} else {
+				matches= false;
+				break;
+			}
+
+			original= originalParent;
+			dupliacte= duplicateParent;
+
+			if ((originalEnclosingBodyDeclaration.equals(original) && !duplicateEnclosingBodyDeclaration.equals(dupliacte))
+					|| (!originalEnclosingBodyDeclaration.equals(original) && duplicateEnclosingBodyDeclaration.equals(dupliacte))) {
+				matches= false;
+				break;
+			}
+		} while (!originalEnclosingBodyDeclaration.equals(original) && !duplicateEnclosingBodyDeclaration.equals(dupliacte));
+
+		return matches;
 	}
 
 	private void initializeDestinations() {
@@ -927,8 +1036,7 @@
 		TextEditGroup description= new TextEditGroup(label);
 		result.addTextEditGroup(description);
 
-		for (int d= 0; d < fDuplicates.length; d++) {
-			SnippetFinder.Match duplicate= fDuplicates[d];
+		for (Match duplicate : fDuplicates) {
 			if (!duplicate.isInvalidNode()) {
 				if (isDestinationReachable(duplicate.getEnclosingMethod())) {
 					ASTNode[] callNodes= createCallNodes(duplicate, modifiers);
@@ -949,8 +1057,7 @@
 		if(!fReplaceDuplicates){
 			return false;
 		}
-		for(int i= 0;i < fDuplicates.length; i++) {
-			SnippetFinder.Match duplicate= fDuplicates[i];
+		for (Match duplicate : fDuplicates) {
 			if(!duplicate.isInvalidNode() && duplicate.isNodeInStaticContext()) {
 				return true;
 			}
diff --git a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SnippetFinder.java b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SnippetFinder.java
index 1597e66..ae14c2c 100644
--- a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SnippetFinder.java
+++ b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SnippetFinder.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -160,7 +160,7 @@
 		reset();
 	}
 
-	public static Match[] perform(ASTNode start, ASTNode[] snippet) {
+	public static List<Match> perform(ASTNode start, ASTNode[] snippet) {
 		Assert.isTrue(start instanceof AbstractTypeDeclaration || start instanceof AnonymousClassDeclaration);
 		SnippetFinder finder= new SnippetFinder(snippet);
 		start.accept(finder);
@@ -174,10 +174,10 @@
 				iter.remove();
 			}
 		}
-		return finder.fResult.toArray(new Match[finder.fResult.size()]);
+		return finder.fResult;
 	}
 
-	private static boolean isLeftHandSideOfAssignment(ASTNode node) {
+	static boolean isLeftHandSideOfAssignment(ASTNode node) {
 		Assignment assignment= (Assignment)ASTNodes.getParent(node, ASTNode.ASSIGNMENT);
 		if (assignment != null) {
 			Expression leftHandSide= assignment.getLeftHandSide();
diff --git a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/ExtractClassRefactoring.java b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/ExtractClassRefactoring.java
index 4d373cf..4879f7e 100644
--- a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/ExtractClassRefactoring.java
+++ b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/ExtractClassRefactoring.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2016 IBM Corporation and others.
+ * Copyright (c) 2007, 2017 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
@@ -76,6 +76,7 @@
 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
+import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.TypeLocation;
 import org.eclipse.jdt.core.refactoring.descriptors.ExtractClassDescriptor;
 import org.eclipse.jdt.core.refactoring.descriptors.ExtractClassDescriptor.Field;
 import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
@@ -83,6 +84,7 @@
 import org.eclipse.jdt.core.search.SearchMatch;
 import org.eclipse.jdt.core.search.SearchPattern;
 
+import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
 import org.eclipse.jdt.internal.corext.codemanipulation.GetterSetterUtil;
 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
@@ -482,7 +484,8 @@
 			TypeDeclaration typeDecl= ASTNodeSearchUtil.getTypeDeclarationNode(fDescriptor.getType(), root);
 			ASTRewrite rewrite= fBaseCURewrite.getASTRewrite();
 			ListRewrite listRewrite= rewrite.getListRewrite(typeDecl, TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
-			TypeDeclaration paramClass= pof.createClassDeclaration(typeDecl.getName().getFullyQualifiedName(), fBaseCURewrite, fieldUpdate);
+			ContextSensitiveImportRewriteContext context= new ContextSensitiveImportRewriteContext(typeDecl, fBaseCURewrite.getImportRewrite());
+			TypeDeclaration paramClass= pof.createClassDeclaration(typeDecl.getName().getFullyQualifiedName(), fBaseCURewrite, fieldUpdate, context);
 			paramClass.modifiers().add(rewrite.getAST().newModifier(ModifierKeyword.PUBLIC_KEYWORD));
 			if (shouldParamClassBeStatic(typeDecl)) {
 				paramClass.modifiers().add(rewrite.getAST().newModifier(ModifierKeyword.STATIC_KEYWORD));
@@ -860,7 +863,7 @@
 		ASTResolving.visitAllBindings(node, new TypeBindingVisitor() {
 			@Override
 			public boolean visit(ITypeBinding nodeBinding) {
-				ParameterObjectFactory.importBinding(nodeBinding, cuRewrite);
+				ParameterObjectFactory.importBinding(nodeBinding, cuRewrite, null, TypeLocation.OTHER);
 				return false;
 			}
 		});
diff --git a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/IntroduceParameterObjectProcessor.java b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/IntroduceParameterObjectProcessor.java
index 43bde33..7b0adf8 100644
--- a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/IntroduceParameterObjectProcessor.java
+++ b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/IntroduceParameterObjectProcessor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -240,6 +240,7 @@
 				final ASTRewrite rewriter= cuRewrite.getASTRewrite();
 				ListRewrite bodyStatements= rewriter.getListRewrite(body, Block.STATEMENTS_PROPERTY);
 				List<ParameterInfo> managedParams= getParameterInfos();
+				ImportRewriteContext context=new ContextSensitiveImportRewriteContext(body, cuRewrite.getImportRewrite());
 				for (Iterator<ParameterInfo> iter= managedParams.iterator(); iter.hasNext();) {
 					final ParameterInfo pi= iter.next();
 					if (isValidField(pi)) {
@@ -255,7 +256,7 @@
 							});
 							pi.setInlined(true);
 						} else {
-							ExpressionStatement initializer= fParameterObjectFactory.createInitializer(pi, getParameterName(), cuRewrite);
+							ExpressionStatement initializer= fParameterObjectFactory.createInitializer(pi, getParameterName(), cuRewrite, context);
 							bodyStatements.insertFirst(initializer, null);
 						}
 					}
@@ -713,9 +714,10 @@
 		} else {
 			ASTRewrite rewriter= cuRewrite.getASTRewrite();
 			TypeDeclaration enclosingType= (TypeDeclaration) methodDeclaration.getParent();
+			ContextSensitiveImportRewriteContext context=new ContextSensitiveImportRewriteContext(enclosingType, cuRewrite.getImportRewrite());
 			ListRewrite bodyRewrite= rewriter.getListRewrite(enclosingType, TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
 			String fqn= enclosingType.getName().getFullyQualifiedName();
-			TypeDeclaration classDeclaration= fParameterObjectFactory.createClassDeclaration(fqn, cuRewrite, null);
+			TypeDeclaration classDeclaration= fParameterObjectFactory.createClassDeclaration(fqn, cuRewrite, null, context);
 			classDeclaration.modifiers().add(rewriter.getAST().newModifier(ModifierKeyword.PUBLIC_KEYWORD));
 			classDeclaration.modifiers().add(rewriter.getAST().newModifier(ModifierKeyword.STATIC_KEYWORD));
 			bodyRewrite.insertBefore(classDeclaration, methodDeclaration, null);
diff --git a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/ParameterObjectFactory.java b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/ParameterObjectFactory.java
index 7a0c0c8..8127072 100644
--- a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/ParameterObjectFactory.java
+++ b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/ParameterObjectFactory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2013 IBM Corporation and others.
+ * Copyright (c) 2007, 2017 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
@@ -68,6 +68,7 @@
 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
+import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.TypeLocation;
 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
 
 import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
@@ -178,10 +179,11 @@
 	 * @param declaringType the fully qualified name of the type
 	 * @param cuRewrite the {@link CompilationUnitRewrite} that will be used for creation
 	 * @param listener the creation listener or null
+	 * @param context the import rewrite context or null
 	 * @return the new declaration
 	 * @throws CoreException if creation failed
 	 */
-	public TypeDeclaration createClassDeclaration(String declaringType, CompilationUnitRewrite cuRewrite, CreationListener listener) throws CoreException {
+	public TypeDeclaration createClassDeclaration(String declaringType, CompilationUnitRewrite cuRewrite, CreationListener listener, ImportRewriteContext context) throws CoreException {
 		AST ast= cuRewrite.getAST();
 		if (listener == null)
 			listener= new CreationListener();
@@ -191,7 +193,7 @@
 		for (Iterator<ParameterInfo> iter= fVariables.iterator(); iter.hasNext();) {
 			ParameterInfo pi= iter.next();
 			if (isValidField(pi)) {
-				FieldDeclaration declaration= createField(pi, cuRewrite);
+				FieldDeclaration declaration= createField(pi, cuRewrite, context);
 				listener.fieldCreated(cuRewrite, declaration, pi);
 				body.add(declaration);
 				ITypeBinding oldTypeBinding= pi.getOldTypeBinding();
@@ -202,18 +204,18 @@
 				}
 			}
 		}
-		MethodDeclaration constructor= createConstructor(declaringType, cuRewrite, listener);
+		MethodDeclaration constructor= createConstructor(declaringType, cuRewrite, listener, context);
 		listener.constructorCreated(cuRewrite, constructor);
 		body.add(constructor);
 		for (Iterator<ParameterInfo> iter= fVariables.iterator(); iter.hasNext();) {
 			ParameterInfo pi= iter.next();
 			if (fCreateGetter && isValidField(pi) && listener.isCreateGetter(pi)) {
-				MethodDeclaration getter= createGetter(pi, declaringType, cuRewrite);
+				MethodDeclaration getter= createGetter(pi, declaringType, cuRewrite, context);
 				listener.getterCreated(cuRewrite, getter, pi);
 				body.add(getter);
 			}
 			if (fCreateSetter && isValidField(pi) && listener.isCreateSetter(pi)) {
-				MethodDeclaration setter= createSetter(pi, declaringType, cuRewrite);
+				MethodDeclaration setter= createSetter(pi, declaringType, cuRewrite, context);
 				listener.setterCreated(cuRewrite, setter, pi);
 				body.add(setter);
 			}
@@ -222,7 +224,7 @@
 		return typeDeclaration;
 	}
 
-	private MethodDeclaration createConstructor(String declaringTypeName, CompilationUnitRewrite cuRewrite, CreationListener listener) throws CoreException {
+	private MethodDeclaration createConstructor(String declaringTypeName, CompilationUnitRewrite cuRewrite, CreationListener listener, ImportRewriteContext context) throws CoreException {
 		AST ast= cuRewrite.getAST();
 		ICompilationUnit unit= cuRewrite.getCu();
 		IJavaProject project= unit.getJavaProject();
@@ -269,7 +271,7 @@
 			String paramName= getParameterName(pi, project, usedParameter);
 			usedParameter.add(paramName);
 
-			Type fieldType= importBinding(typeBinding, cuRewrite);
+			Type fieldType= importBinding(typeBinding, cuRewrite, context, TypeLocation.PARAMETER);
 			svd.setType(fieldType);
 			svd.setName(ast.newSimpleName(paramName));
 			parameters.add(svd);
@@ -298,18 +300,18 @@
 	}
 
 
-	public static Type importBinding(ITypeBinding typeBinding, CompilationUnitRewrite cuRewrite) {
+	public static Type importBinding(ITypeBinding typeBinding, CompilationUnitRewrite cuRewrite, ImportRewriteContext context, TypeLocation typeLocation) {
 		int declaredModifiers= typeBinding.getModifiers();
 		AST ast= cuRewrite.getAST();
 		if (Modifier.isPrivate(declaredModifiers) || Modifier.isProtected(declaredModifiers)) {
 			return ast.newSimpleType(ast.newSimpleName(typeBinding.getName()));
 		}
-		Type type= cuRewrite.getImportRewrite().addImport(typeBinding, cuRewrite.getAST());
+		Type type= cuRewrite.getImportRewrite().addImport(typeBinding, cuRewrite.getAST(), context, typeLocation);
 		cuRewrite.getImportRemover().registerAddedImports(type);
 		return type;
 	}
 
-	private FieldDeclaration createField(ParameterInfo pi, CompilationUnitRewrite cuRewrite) throws CoreException {
+	private FieldDeclaration createField(ParameterInfo pi, CompilationUnitRewrite cuRewrite, ImportRewriteContext context) throws CoreException {
 		AST ast= cuRewrite.getAST();
 		ICompilationUnit unit= cuRewrite.getCu();
 
@@ -332,7 +334,7 @@
 			modifiers.add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
 		}
 		declaration.modifiers().addAll(modifiers);
-		declaration.setType(importBinding(pi.getNewTypeBinding(), cuRewrite));
+		declaration.setType(importBinding(pi.getNewTypeBinding(), cuRewrite, context, TypeLocation.FIELD));
 		return declaration;
 	}
 
@@ -391,7 +393,7 @@
 		return fa;
 	}
 
-	private MethodDeclaration createGetter(ParameterInfo pi, String declaringType, CompilationUnitRewrite cuRewrite) throws CoreException {
+	private MethodDeclaration createGetter(ParameterInfo pi, String declaringType, CompilationUnitRewrite cuRewrite, ImportRewriteContext context) throws CoreException {
 		AST ast= cuRewrite.getAST();
 		ICompilationUnit cu= cuRewrite.getCu();
 		IJavaProject project= cu.getJavaProject();
@@ -407,7 +409,7 @@
 				methodDeclaration.setJavadoc((Javadoc) cuRewrite.getASTRewrite().createStringPlaceholder(comment, ASTNode.JAVADOC));
 		}
 		methodDeclaration.setName(ast.newSimpleName(getterName));
-		methodDeclaration.setReturnType2(importBinding(pi.getNewTypeBinding(), cuRewrite));
+		methodDeclaration.setReturnType2(importBinding(pi.getNewTypeBinding(), cuRewrite, context, TypeLocation.RETURN_TYPE));
 		methodDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
 		Block block= ast.newBlock();
 		methodDeclaration.setBody(block);
@@ -421,7 +423,7 @@
 		return methodDeclaration;
 	}
 
-	public ExpressionStatement createInitializer(ParameterInfo pi, String paramName, CompilationUnitRewrite cuRewrite) {
+	public ExpressionStatement createInitializer(ParameterInfo pi, String paramName, CompilationUnitRewrite cuRewrite, ImportRewriteContext context) {
 		AST ast= cuRewrite.getAST();
 
 		VariableDeclarationFragment fragment= ast.newVariableDeclarationFragment();
@@ -429,14 +431,14 @@
 		fragment.setInitializer(createFieldReadAccess(pi, paramName, ast, cuRewrite.getCu().getJavaProject(), false, null));
 		VariableDeclarationExpression declaration= ast.newVariableDeclarationExpression(fragment);
 		IVariableBinding variable= pi.getOldBinding();
-		declaration.setType(importBinding(pi.getNewTypeBinding(), cuRewrite));
+		declaration.setType(importBinding(pi.getNewTypeBinding(), cuRewrite, context, TypeLocation.LOCAL_VARIABLE));
 		int modifiers= variable.getModifiers();
 		List<Modifier> newModifiers= ast.newModifiers(modifiers);
 		declaration.modifiers().addAll(newModifiers);
 		return ast.newExpressionStatement(declaration);
 	}
 
-	private MethodDeclaration createSetter(ParameterInfo pi, String declaringType, CompilationUnitRewrite cuRewrite) throws CoreException {
+	private MethodDeclaration createSetter(ParameterInfo pi, String declaringType, CompilationUnitRewrite cuRewrite, ImportRewriteContext context) throws CoreException {
 		AST ast= cuRewrite.getAST();
 		ICompilationUnit cu= cuRewrite.getCu();
 		IJavaProject project= cu.getJavaProject();
@@ -455,7 +457,7 @@
 		methodDeclaration.setName(ast.newSimpleName(setterName));
 		methodDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
 		SingleVariableDeclaration variable= ast.newSingleVariableDeclaration();
-		variable.setType(importBinding(pi.getNewTypeBinding(), cuRewrite));
+		variable.setType(importBinding(pi.getNewTypeBinding(), cuRewrite, context, TypeLocation.PARAMETER));
 		variable.setName(ast.newSimpleName(paramName));
 		methodDeclaration.parameters().add(variable);
 		Block block= ast.newBlock();
@@ -646,12 +648,13 @@
 			CompilationUnit root= cuRewrite.getRoot();
 			AST ast= cuRewrite.getAST();
 			ImportRewrite importRewrite= cuRewrite.getImportRewrite();
+			ContextSensitiveImportRewriteContext context=new ContextSensitiveImportRewriteContext(root, cuRewrite.getImportRewrite());
 
 			// retrieve&replace dummy type with real class
 			ListRewrite types= rewriter.getListRewrite(root, CompilationUnit.TYPES_PROPERTY);
 			ASTNode dummyType= (ASTNode) types.getOriginalList().get(0);
 			String newTypeName= JavaModelUtil.concatenateName(getPackage(), getClassName());
-			TypeDeclaration classDeclaration= createClassDeclaration(newTypeName, cuRewrite, listener);
+			TypeDeclaration classDeclaration= createClassDeclaration(newTypeName, cuRewrite, listener, context);
 			classDeclaration.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
 			Javadoc javadoc= (Javadoc) dummyType.getStructuralProperty(TypeDeclaration.JAVADOC_PROPERTY);
 			rewriter.set(classDeclaration, TypeDeclaration.JAVADOC_PROPERTY, javadoc, null);
diff --git a/org.eclipse.jdt.ui/css/e4-dark_jdt_syntaxhighlighting.css b/org.eclipse.jdt.ui/css/e4-dark_jdt_syntaxhighlighting.css
index cb28e79..4abdf04 100644
--- a/org.eclipse.jdt.ui/css/e4-dark_jdt_syntaxhighlighting.css
+++ b/org.eclipse.jdt.ui/css/e4-dark_jdt_syntaxhighlighting.css
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2014, 2016 Lars Vogel and others.
+ * Copyright (c) 2014, 2017 Lars Vogel and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -12,7 +12,7 @@
 
 /* ############################## JDT syntax highlighting ############################## */
 
-IEclipsePreferences#org-eclipse-jdt-ui {
+IEclipsePreferences#org-eclipse-jdt-ui:org-eclipse-jdt-ui { /* pseudo attribute added to allow contributions without replacing this node, see Bug 466075 */
 	preferences:
 		'content_assist_completion_replacement_background=200,200,0'
 		'content_assist_completion_replacement_foreground=200,0,0'
diff --git a/org.eclipse.jdt.ui/dictionaries/en_GB.dictionary b/org.eclipse.jdt.ui/dictionaries/en_GB.dictionary
index e65e4af..52ecda6 100644
--- a/org.eclipse.jdt.ui/dictionaries/en_GB.dictionary
+++ b/org.eclipse.jdt.ui/dictionaries/en_GB.dictionary
@@ -10614,6 +10614,7 @@
 connector's
 connectors
 connects
+connexion
 connoisseur
 connoisseur's
 connoisseurs
@@ -14511,6 +14512,7 @@
 ditcher
 ditches
 ditching
+ditto
 divan
 divan's
 divans
@@ -15293,6 +15295,7 @@
 eccentrics
 ecclesiastical
 ecclesiastically
+echelon
 echo
 echoed
 echoes
@@ -30988,6 +30991,7 @@
 pixel
 pixel's
 pixels
+pizza
 placard
 placard's
 placards
@@ -34989,6 +34993,7 @@
 replenisher
 replenishes
 replenishing
+replenishment
 replete
 repleteness
 repletion
@@ -39273,6 +39278,7 @@
 spiller
 spilling
 spills
+spilt
 spin
 spinach
 spinal
@@ -46804,6 +46810,7 @@
 women
 women's
 womens
+won
 won't
 wonder
 wondered
diff --git a/org.eclipse.jdt.ui/dictionaries/en_US.dictionary b/org.eclipse.jdt.ui/dictionaries/en_US.dictionary
index f729b82..05f2ca7 100644
--- a/org.eclipse.jdt.ui/dictionaries/en_US.dictionary
+++ b/org.eclipse.jdt.ui/dictionaries/en_US.dictionary
@@ -14511,6 +14511,7 @@
 ditcher
 ditches
 ditching
+ditto
 divan
 divan's
 divans
@@ -15293,6 +15294,7 @@
 eccentrics
 ecclesiastical
 ecclesiastically
+echelon
 echo
 echoed
 echoes
@@ -30988,6 +30990,7 @@
 pixel
 pixel's
 pixels
+pizza
 placard
 placard's
 placards
@@ -34989,6 +34992,7 @@
 replenisher
 replenishes
 replenishing
+replenishment
 replete
 repleteness
 repletion
@@ -39273,6 +39277,7 @@
 spiller
 spilling
 spills
+spilt
 spin
 spinach
 spinal
@@ -46804,6 +46809,7 @@
 women
 women's
 womens
+won
 won't
 wonder
 wondered
diff --git a/org.eclipse.jdt.ui/ui refactoring/org/eclipse/jdt/internal/ui/refactoring/reorg/PasteAction.java b/org.eclipse.jdt.ui/ui refactoring/org/eclipse/jdt/internal/ui/refactoring/reorg/PasteAction.java
index 1e156c3..a4b1e18 100644
--- a/org.eclipse.jdt.ui/ui refactoring/org/eclipse/jdt/internal/ui/refactoring/reorg/PasteAction.java
+++ b/org.eclipse.jdt.ui/ui refactoring/org/eclipse/jdt/internal/ui/refactoring/reorg/PasteAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -123,8 +123,11 @@
 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
 import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
 
+import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
+import org.eclipse.jdt.internal.core.manipulation.util.Strings;
 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
 import org.eclipse.jdt.internal.corext.dom.BodyDeclarationRewrite;
+import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
 import org.eclipse.jdt.internal.corext.refactoring.Checks;
 import org.eclipse.jdt.internal.corext.refactoring.TypedSource;
 import org.eclipse.jdt.internal.corext.refactoring.changes.TextChangeCompatibility;
@@ -140,7 +143,6 @@
 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
 import org.eclipse.jdt.internal.corext.util.JdtFlags;
 import org.eclipse.jdt.internal.corext.util.Messages;
-import org.eclipse.jdt.internal.core.manipulation.util.Strings;
 
 import org.eclipse.jdt.launching.IVMInstall;
 import org.eclipse.jdt.launching.IVMInstall2;
@@ -159,14 +161,12 @@
 import org.eclipse.jdt.internal.ui.IJavaStatusConstants;
 import org.eclipse.jdt.internal.ui.JavaPlugin;
 import org.eclipse.jdt.internal.ui.JavaUIMessages;
-import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
 import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
 import org.eclipse.jdt.internal.ui.refactoring.RefactoringExecutionHelper;
 import org.eclipse.jdt.internal.ui.refactoring.RefactoringMessages;
 import org.eclipse.jdt.internal.ui.util.BusyIndicatorRunnableContext;
 import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
 import org.eclipse.jdt.internal.ui.util.SelectionUtil;
-import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
 import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathsBlock;
 import org.eclipse.jdt.internal.ui.workingsets.IWorkingSetIDs;
 
@@ -1296,7 +1296,7 @@
 
 				return true;
 			} else {
-				if (isJavaProject && !((IJavaProject)target).isOpen())
+				if (isJavaProject && !((IJavaProject) target).getProject().isOpen())
 					return false;
 
 				IJavaElement element= (IJavaElement)target;
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/JavadocView.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/JavadocView.java
index 1ae9521..48c361b 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/JavadocView.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/infoviews/JavadocView.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -104,6 +104,7 @@
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.ILocalVariable;
 import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IMethod;
 import org.eclipse.jdt.core.IPackageDeclaration;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
@@ -124,6 +125,8 @@
 import org.eclipse.jdt.core.dom.NodeFinder;
 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
 
+import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
+import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
 import org.eclipse.jdt.internal.corext.javadoc.JavaDocLocations;
 import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
@@ -144,12 +147,10 @@
 import org.eclipse.jdt.internal.ui.JavaPluginImages;
 import org.eclipse.jdt.internal.ui.actions.ActionMessages;
 import org.eclipse.jdt.internal.ui.actions.SimpleSelectionProvider;
-import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
 import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
 import org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover;
 import org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover.FallbackInformationPresenter;
 import org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2;
-import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
 import org.eclipse.jdt.internal.ui.viewsupport.BindingLinkedLabelComposer;
 import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks;
 
@@ -991,14 +992,14 @@
 				HTMLPrinter.startBulletList(buffer);
 				IJavaElement curr= result[i];
 				if (curr instanceof IMember || curr instanceof IPackageFragment || curr instanceof IPackageDeclaration || curr.getElementType() == IJavaElement.LOCAL_VARIABLE) {
-					HTMLPrinter.addBullet(buffer, getInfoText(curr, null, false));
+					HTMLPrinter.addBullet(buffer, getInfoText(curr, null, null, false));
 					HTMLPrinter.endBulletList(buffer);
 				}
 			}
 		} else {
 			IJavaElement curr= result[0];
 			if (curr instanceof IPackageDeclaration || curr instanceof IPackageFragment) {
-				HTMLPrinter.addSmallHeader(buffer, getInfoText(curr, null, true));
+				HTMLPrinter.addSmallHeader(buffer, getInfoText(curr, null, null, true));
 				buffer.append("<br>"); //$NON-NLS-1$
 				Reader reader= null;
 				String content= null;
@@ -1048,19 +1049,11 @@
 			} else if (curr instanceof IMember || curr instanceof ILocalVariable || curr instanceof ITypeParameter) {
 				final IJavaElement element= curr;
 
-				String constantValue= null;
-				if (element instanceof IField) {
-					constantValue= computeFieldConstant(activePart, selection, (IField) element, monitor);
-					if (constantValue != null)
-						constantValue= HTMLPrinter.convertToHTMLContentWithWhitespace(constantValue);
-				}
-
-				HTMLPrinter.addSmallHeader(buffer, getInfoText(element, constantValue, true));
-
+				ITypeRoot typeRoot= null;
+				Region hoverRegion= null;
 				try {
 					ISourceRange nameRange= ((ISourceReference) curr).getNameRange();
 					if (SourceRange.isAvailable(nameRange)) {
-						ITypeRoot typeRoot;
 						if (element instanceof ILocalVariable) {
 							typeRoot= ((ILocalVariable) curr).getTypeRoot();
 						} else if (element instanceof ITypeParameter) {
@@ -1068,14 +1061,38 @@
 						} else {
 							typeRoot= ((IMember) curr).getTypeRoot();
 						}
-						Region hoverRegion= new Region(nameRange.getOffset(), nameRange.getLength());
-						buffer.append("<br>"); //$NON-NLS-1$
-						JavadocHover.addAnnotations(buffer, curr, typeRoot, hoverRegion);
+						hoverRegion= new Region(nameRange.getOffset(), nameRange.getLength());
 					}
 				} catch (JavaModelException e) {
 					// no annotations this time...
 				}
 
+				String constantValue= null;
+				if (element instanceof IField) {
+					constantValue= computeFieldConstant(activePart, selection, (IField) element, monitor);
+					if (constantValue != null)
+						constantValue= HTMLPrinter.convertToHTMLContentWithWhitespace(constantValue);
+				}
+
+				String defaultValue= null;
+				if (element instanceof IMethod) {
+					try {
+						defaultValue= JavadocHover.getAnnotationMemberDefaultValue((IMethod) element, typeRoot, hoverRegion);
+						if (defaultValue != null) {
+							defaultValue= HTMLPrinter.convertToHTMLContentWithWhitespace(defaultValue);
+						}
+					} catch (JavaModelException e) {
+						// no default value
+					}
+				}
+
+				HTMLPrinter.addSmallHeader(buffer, getInfoText(element, constantValue, defaultValue, true));
+
+				if (typeRoot != null && hoverRegion != null) {
+					buffer.append("<br>"); //$NON-NLS-1$
+					JavadocHover.addAnnotations(buffer, curr, typeRoot, hoverRegion);
+				}
+
 				Reader reader= null;
 				try {
 					String content= JavadocContentAccess2.getHTMLContent(element, true);
@@ -1128,10 +1145,11 @@
 	 * 
 	 * @param member the Java member
 	 * @param constantValue the constant value if any
+	 * @param defaultValue the default value of the annotation type member, if any
 	 * @param allowImage <code>true</code> if the Java element image should be shown
 	 * @return a string containing the member's label
 	 */
-	private String getInfoText(IJavaElement member, String constantValue, boolean allowImage) {
+	private String getInfoText(IJavaElement member, String constantValue, String defaultValue, boolean allowImage) {
 		long flags= JavadocHover.getHeaderFlags(member);
 		IBinding binding= JavadocHover.getHoverBinding(member, null);
 		StringBuffer label;
@@ -1146,6 +1164,9 @@
 		}
 		if (member.getElementType() == IJavaElement.FIELD && constantValue != null) {
 			label.append(constantValue);
+		} else if (member.getElementType() == IJavaElement.METHOD && defaultValue != null) {
+			label.append(JavadocHover.CONSTANT_VALUE_SEPARATOR);
+			label.append(defaultValue);
 		}
 		return JavadocHover.getImageAndLabel(member, allowImage, label.toString());
 	}
@@ -1272,7 +1293,7 @@
 	 *
 	 * @param activePart the part that triggered the computation, or <code>null</code>
 	 * @param selection the selection that references the field, or <code>null</code>
-	 * @param resolvedField the filed whose constant value will be computed
+	 * @param resolvedField the field whose constant value will be computed
 	 * @param monitor the progress monitor
 	 *
 	 * @return the textual representation of the constant, or <code>null</code> if the
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javadocexport/JavadocOptionsManager.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javadocexport/JavadocOptionsManager.java
index 25bd2dd..d7c9508 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javadocexport/JavadocOptionsManager.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/javadocexport/JavadocOptionsManager.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -56,6 +56,7 @@
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 
+import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
 import org.eclipse.jdt.internal.corext.util.Messages;
 
 import org.eclipse.jdt.launching.ExecutionArguments;
@@ -69,7 +70,6 @@
 import org.eclipse.jdt.internal.ui.JavaPlugin;
 import org.eclipse.jdt.internal.ui.JavaUIStatus;
 import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
-import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
 
 
 public class JavadocOptionsManager {
@@ -219,7 +219,7 @@
 				return null;
 			}
 		}
-		if (res != null && res.isOpen()) {
+		if (res != null && res.getProject().isOpen()) {
 			return res;
 		}
 		return null;
@@ -1089,7 +1089,7 @@
 	}
 
 	private boolean isValidProject(IJavaProject project) {
-		if (project != null && project.exists() && project.isOpen()) {
+		if (project != null && project.exists() && project.getProject().isOpen()) {
 			return true;
 		}
 		return false;
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/JavaBasePreferencePage.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/JavaBasePreferencePage.java
index 148b2e1..f0261f5 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/JavaBasePreferencePage.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/JavaBasePreferencePage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,6 +13,7 @@
 import java.util.ArrayList;
 
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.layout.GridData;
@@ -24,6 +25,7 @@
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Text;
 
+import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.core.runtime.preferences.InstanceScope;
 
 import org.eclipse.jface.dialogs.Dialog;
@@ -70,6 +72,8 @@
 	private ArrayList<Text> fTextControls;
 
 	private IPreferenceStore fJavaCorePreferences;
+	private static final String ENABLE_NEW_JAVA_INDEX= "enableNewJavaIndex"; //JavaIndex.ENABLE_NEW_JAVA_INDEX //$NON-NLS-1$
+
 
 	public JavaBasePreferencePage() {
 		super();
@@ -188,7 +192,22 @@
 		group.setText(PreferencesMessages.JavaBasePreferencePage_search);
 
 		addCheckBox(group, PreferencesMessages.JavaBasePreferencePage_search_small_menu, null, PreferenceConstants.SEARCH_USE_REDUCED_MENU);
-		addCheckBox(group, PreferencesMessages.JavaBasePreferencePage_DisableNewJavaIndex, fJavaCorePreferences, "disableNewJavaIndex"); //$NON-NLS-1$
+		addCheckBox(group, PreferencesMessages.JavaBasePreferencePage_EnableNewJavaIndex, fJavaCorePreferences, ENABLE_NEW_JAVA_INDEX);
+
+		Button rebuildIndexButton= new Button(group, SWT.PUSH);
+		rebuildIndexButton.setText(PreferencesMessages.JavaBasePreferencePage_rebuildIndexButtonName);
+		rebuildIndexButton.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, false, false));
+		rebuildIndexButton.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				Job job= Job.create(PreferencesMessages.JavaBasePreferencePage_rebuildingIndexJobName, monitor -> {
+					JavaCore.rebuildIndex(monitor);
+				});
+				job.setUser(true);
+				job.schedule();
+			}
+		});
+		SWTUtil.setButtonDimensionHint(rebuildIndexButton);
 
 		layout= new GridLayout();
 		layout.numColumns= 2;
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.java
index f1adb32..bc50820 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.java
@@ -100,6 +100,8 @@
 	public static String ImportOrganizeInputDialog_error_entryExists;
 	public static String ImportOrganizeInputDialog_name_group_label;
 	public static String ImportOrganizeInputDialog_name_group_static_label;
+	public static String JavaBasePreferencePage_rebuildingIndexJobName;
+	public static String JavaBasePreferencePage_rebuildIndexButtonName;
 	public static String JavaBasePreferencePage_description;
 	public static String JavaBasePreferencePage_doubleclick_action;
 	public static String JavaBasePreferencePage_doubleclick_gointo;
@@ -798,7 +800,7 @@
 	public static String ComplianceConfigurationBlock_jrecompliance_info_project;
 	public static String ProblemSeveritiesConfigurationBlock_section_generics;
 	public static String JavaBasePreferencePage_dialogs;
-	public static String JavaBasePreferencePage_DisableNewJavaIndex;
+	public static String JavaBasePreferencePage_EnableNewJavaIndex;
 	public static String JavaBasePreferencePage_do_not_hide_description;
 	public static String JavaBasePreferencePage_do_not_hide_button;
 	public static String JavaBasePreferencePage_do_not_hide_dialog_title;
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.properties b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.properties
index 7bcf34b..edad88b 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.properties
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/PreferencesMessages.properties
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2000, 2016 IBM Corporation and others.
+# Copyright (c) 2000, 2017 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
@@ -77,6 +77,8 @@
 ImportOrganizeInputDialog_error_entryExists=Entry already exists in list.
 ImportOrganizeInputDialog_name_group_label=&Enter a prefix (e.g. 'org.eclipse') or '*' to match all imports:
 ImportOrganizeInputDialog_name_group_static_label=&Enter a prefix (e.g. 'org.eclipse') or '*' to match all imports:
+JavaBasePreferencePage_rebuildingIndexJobName=Rebuilding Java index
+JavaBasePreferencePage_rebuildIndexButtonName=Re&build Index
 JavaBasePreferencePage_description=General settings for Java development:
 
 JavaBasePreferencePage_doubleclick_action=Action on double click in the Package Explorer
@@ -201,7 +203,7 @@
 JavaBasePreferencePage_openTypeHierarchy=When opening a Type Hierarchy
 JavaBasePreferencePage_inView=Show the &Type Hierarchy View in the current perspective
 JavaBasePreferencePage_dialogs=Java dialogs
-JavaBasePreferencePage_DisableNewJavaIndex=Disable &new Java index
+JavaBasePreferencePage_EnableNewJavaIndex=Enable &new Java index
 JavaBasePreferencePage_inPerspective=Open a new Type Hierarchy &Perspective
 
 JavaEditorPreferencePage_quickassist_lightbulb=L&ight bulb for quick assists
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/formatter/ProfileVersioner.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/formatter/ProfileVersioner.java
index 8eafe64..80b1909 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/formatter/ProfileVersioner.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/preferences/formatter/ProfileVersioner.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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,8 +40,9 @@
 	private static final int VERSION_10= 10; // splitting options for annotation types
 	private static final int VERSION_11= 11; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=49412
 	private static final int VERSION_12= 12; // https://bugs.eclipse.org/318010
+	private static final int VERSION_13= 13; // https://bugs.eclipse.org/514019
 
-	private static final int CURRENT_VERSION= VERSION_12;
+	private static final int CURRENT_VERSION= VERSION_13;
 
 	@Override
 	public int getFirstVersion() {
@@ -100,6 +101,9 @@
 		case VERSION_11 :
 			version11to12(oldSettings);
 			//$FALL-THROUGH$
+		case VERSION_12 :
+			version12to13(oldSettings);
+			//$FALL-THROUGH$
 		default:
 		    for (final Iterator<String> iter= oldSettings.keySet().iterator(); iter.hasNext(); ) {
 		        final String key= iter.next();
@@ -616,8 +620,13 @@
 				DefaultCodeFormatterConstants.FORMATTER_INSERT_NEW_LINE_AFTER_ANNOTATION_ON_TYPE
 		});
 	}
-	
-	
+
+	private static void version12to13(Map<String, String> oldSettings) {
+		oldSettings.put(DefaultCodeFormatterConstants.FORMATTER_COMMENT_COUNT_LINE_LENGTH_FROM_STARTING_POSITION,
+				DefaultCodeFormatterConstants.FALSE);
+	}
+
+
 	/* old format constant values */
 
     private static final String FORMATTER_METHOD_DECLARATION_ARGUMENTS_ALIGNMENT = JavaCore.PLUGIN_ID + ".formatter.method_declaration_arguments_alignment"; //$NON-NLS-1$
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/search/JavaSearchResultPage.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/search/JavaSearchResultPage.java
index 4bf28e2..d8f66df 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/search/JavaSearchResultPage.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/search/JavaSearchResultPage.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -417,7 +417,7 @@
 		super.restoreState(memento);
 
 		int sortOrder= SortingLabelProvider.SHOW_ELEMENT_CONTAINER;
-		int grouping= LevelTreeContentProvider.LEVEL_PACKAGE;
+		int grouping= LevelTreeContentProvider.LEVEL_PROJECT;
 		int elementLimit= DEFAULT_ELEMENT_LIMIT;
 
 		try {
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java
index e61cab0..78faa07 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickAssistProcessor.java
@@ -130,6 +130,7 @@
 import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
 import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
+import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility2;
 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
 import org.eclipse.jdt.internal.corext.dom.Bindings;
@@ -1225,7 +1226,9 @@
 				typeMethodReference.setName((SimpleName) rewrite.createCopyTarget(methodInvocation.getName()));
 				importRewrite= StubUtility.createImportRewrite(context.getASTRoot(), true);
 				ITypeBinding invocationTypeBinding= ASTNodes.getInvocationType(methodInvocation, methodBinding, invocationQualifier);
-				typeMethodReference.setType(importRewrite.addImport(invocationTypeBinding, ast));
+				invocationTypeBinding=StubUtility2.replaceWildcardsAndCaptures(invocationTypeBinding);
+				ImportRewriteContext importRewriteContext=new ContextSensitiveImportRewriteContext(lambda, importRewrite);
+				typeMethodReference.setType(importRewrite.addImport(invocationTypeBinding, ast, importRewriteContext, TypeLocation.OTHER));
 				typeMethodReference.typeArguments().addAll(getCopiedTypeArguments(rewrite, methodInvocation.typeArguments()));
 
 			} else {
@@ -1384,13 +1387,14 @@
 		ImportRewrite importRewrite= StubUtility.createImportRewrite(context.getASTRoot(), true);
 
 		rewrite.set(lambda, LambdaExpression.PARENTHESES_PROPERTY, Boolean.valueOf(true), null);
-
+		ContextSensitiveImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(lambda, importRewrite);
 		ITypeBinding[] parameterTypes= methodBinding.getParameterTypes();
 		for (int i= 0; i < noOfLambdaParams; i++) {
 			VariableDeclaration param= lambdaParameters.get(i);
 			SingleVariableDeclaration newParam= ast.newSingleVariableDeclaration();
 			newParam.setName(ast.newSimpleName(param.getName().getIdentifier()));
-			newParam.setType(importRewrite.addImport(parameterTypes[i], ast));
+			ITypeBinding type= StubUtility2.replaceWildcardsAndCaptures(parameterTypes[i]);
+			newParam.setType(importRewrite.addImport(type, ast, importRewriteContext, TypeLocation.PARAMETER));
 			rewrite.replace(param, newParam, null);
 		}
 
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickFixProcessor.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickFixProcessor.java
index 41ee85d..38b7ccc 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickFixProcessor.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/QuickFixProcessor.java
@@ -263,6 +263,7 @@
 			case IProblem.ParameterLackingNonNullAnnotation:
 			case IProblem.ParameterLackingNullableAnnotation:
 			case IProblem.SpecdNonNullLocalVariableComparisonYieldsFalse:
+			case IProblem.RedundantNullCheckAgainstNonNullType:
 			case IProblem.RedundantNullCheckOnSpecdNonNullLocalVariable:
 			case IProblem.RedundantNullAnnotation:
 			case IProblem.UnusedTypeParameter:
@@ -750,6 +751,7 @@
 				NullAnnotationsCorrectionProcessor.addReturnAndArgumentTypeProposal(context, problem, ChangeKind.LOCAL, proposals);
 				NullAnnotationsCorrectionProcessor.addReturnAndArgumentTypeProposal(context, problem, ChangeKind.TARGET, proposals);
 				break;
+			case IProblem.RedundantNullCheckAgainstNonNullType:
 			case IProblem.SpecdNonNullLocalVariableComparisonYieldsFalse:
 			case IProblem.RedundantNullCheckOnSpecdNonNullLocalVariable:
 				IJavaProject prj = context.getCompilationUnit().getJavaProject();
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/proposals/ChangeMethodSignatureProposal.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/proposals/ChangeMethodSignatureProposal.java
index c9b397c..58b3166 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/proposals/ChangeMethodSignatureProposal.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/proposals/ChangeMethodSignatureProposal.java
@@ -50,6 +50,7 @@
 import org.eclipse.jdt.internal.corext.dom.DimensionRewrite;
 import org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder;
 import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
+import org.eclipse.jdt.internal.corext.dom.TypeAnnotationRewrite;
 
 import org.eclipse.jdt.internal.ui.text.correction.JavadocTagsSubProcessor;
 
@@ -214,6 +215,7 @@
 				Type newType= imports.addImport(newTypeBinding, ast, context, TypeLocation.PARAMETER);
 				rewrite.replace(decl.getType(), newType, null);
 				DimensionRewrite.removeAllChildren(decl, SingleVariableDeclaration.EXTRA_DIMENSIONS2_PROPERTY, rewrite, null);
+				TypeAnnotationRewrite.removePureTypeAnnotations(decl, SingleVariableDeclaration.MODIFIERS2_PROPERTY, rewrite, null);
 
 				IBinding binding= decl.getName().resolveBinding();
 				if (binding != null) {
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/proposals/TypeChangeCorrectionProposal.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/proposals/TypeChangeCorrectionProposal.java
index 276b689..677c310 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/proposals/TypeChangeCorrectionProposal.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/proposals/TypeChangeCorrectionProposal.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -42,11 +42,13 @@
 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
+import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.TypeLocation;
 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
 
 import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
 import org.eclipse.jdt.internal.corext.dom.Bindings;
 import org.eclipse.jdt.internal.corext.dom.DimensionRewrite;
+import org.eclipse.jdt.internal.corext.dom.TypeAnnotationRewrite;
 import org.eclipse.jdt.internal.corext.util.Messages;
 
 import org.eclipse.jdt.ui.JavaElementLabels;
@@ -65,6 +67,7 @@
 	private final CompilationUnit fAstRoot;
 	private final ITypeBinding fNewType;
 	private final ITypeBinding[] fTypeProposals;
+	private final TypeLocation fTypeLocation;
 
 	public TypeChangeCorrectionProposal(ICompilationUnit targetCU, IBinding binding, CompilationUnit astRoot, ITypeBinding newType, boolean offerSuperTypeProposals, int relevance) {
 		super("", targetCU, null, relevance, JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE)); //$NON-NLS-1$
@@ -88,14 +91,18 @@
 			IVariableBinding varBinding= (IVariableBinding) binding;
 			String[] args= { BasicElementLabels.getJavaElementName(varBinding.getName()),  BasicElementLabels.getJavaElementName(typeName)};
 			if (varBinding.isField()) {
+				fTypeLocation= TypeLocation.FIELD;
 				setDisplayName(Messages.format(CorrectionMessages.TypeChangeCompletionProposal_field_name, args));
 			} else if (astRoot.findDeclaringNode(binding) instanceof SingleVariableDeclaration) {
+				fTypeLocation= TypeLocation.PARAMETER;
 				setDisplayName(Messages.format(CorrectionMessages.TypeChangeCompletionProposal_param_name, args));
 			} else {
+				fTypeLocation= TypeLocation.LOCAL_VARIABLE;
 				setDisplayName(Messages.format(CorrectionMessages.TypeChangeCompletionProposal_variable_name, args));
 			}
 		} else {
 			String[] args= { binding.getName(), typeName };
+			fTypeLocation= TypeLocation.RETURN_TYPE;
 			setDisplayName(Messages.format(CorrectionMessages.TypeChangeCompletionProposal_method_name, args));
 		}
 	}
@@ -117,13 +124,14 @@
 			ImportRewrite imports= createImportRewrite(newRoot);
 
 			ImportRewriteContext context= new ContextSensitiveImportRewriteContext(newRoot, declNode.getStartPosition(), imports);
-			Type type= imports.addImport(fNewType, ast, context);
+			Type type= imports.addImport(fNewType, ast, context, fTypeLocation);
 
 			if (declNode instanceof MethodDeclaration) {
 				MethodDeclaration methodDecl= (MethodDeclaration) declNode;
 				Type origReturnType= methodDecl.getReturnType2();
 				rewrite.set(methodDecl, MethodDeclaration.RETURN_TYPE2_PROPERTY, type, null);
 				DimensionRewrite.removeAllChildren(methodDecl, MethodDeclaration.EXTRA_DIMENSIONS2_PROPERTY, rewrite, null);
+				TypeAnnotationRewrite.removePureTypeAnnotations(methodDecl, MethodDeclaration.MODIFIERS2_PROPERTY, rewrite, null);
 				// add javadoc tag
 				Javadoc javadoc= methodDecl.getJavadoc();
 				if (javadoc != null && origReturnType != null && origReturnType.isPrimitiveType()
@@ -164,6 +172,7 @@
 					} else {
 						rewrite.set(fieldDecl, FieldDeclaration.TYPE_PROPERTY, type, null);
 						DimensionRewrite.removeAllChildren(declNode, VariableDeclarationFragment.EXTRA_DIMENSIONS2_PROPERTY, rewrite, null);
+						TypeAnnotationRewrite.removePureTypeAnnotations(fieldDecl, FieldDeclaration.MODIFIERS2_PROPERTY, rewrite, null);
 					}
 				} else if (parent instanceof VariableDeclarationStatement) {
 					VariableDeclarationStatement varDecl= (VariableDeclarationStatement) parent;
@@ -192,6 +201,7 @@
 				SingleVariableDeclaration variableDeclaration= (SingleVariableDeclaration) declNode;
 				rewrite.set(variableDeclaration, SingleVariableDeclaration.TYPE_PROPERTY, type, null);
 				DimensionRewrite.removeAllChildren(declNode, SingleVariableDeclaration.EXTRA_DIMENSIONS2_PROPERTY, rewrite, null);
+				TypeAnnotationRewrite.removePureTypeAnnotations(declNode, SingleVariableDeclaration.MODIFIERS2_PROPERTY, rewrite, null);
 			}
 
 			// set up linked mode
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/AbstractJavaCompletionProposal.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/AbstractJavaCompletionProposal.java
index b76f483..f1bc40e 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/AbstractJavaCompletionProposal.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/AbstractJavaCompletionProposal.java
@@ -44,6 +44,7 @@
 import org.eclipse.jface.internal.text.html.HTMLPrinter;
 import org.eclipse.jface.preference.IPreferenceStore;
 import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.resource.ColorRegistry;
 import org.eclipse.jface.resource.JFaceResources;
 import org.eclipse.jface.viewers.StyledString;
 
@@ -602,8 +603,12 @@
 			String info= getProposalInfo().getInfo(monitor);
 			if (info != null && info.length() > 0) {
 				StringBuffer buffer= new StringBuffer();
-				HTMLPrinter.insertPageProlog(buffer, 0, getCSSStyles());
 
+				ColorRegistry registry = JFaceResources.getColorRegistry();
+				RGB fgRGB = registry.getRGB("org.eclipse.jdt.ui.Javadoc.foregroundColor"); //$NON-NLS-1$ 
+				RGB bgRGB= registry.getRGB("org.eclipse.jdt.ui.Javadoc.backgroundColor"); //$NON-NLS-1$ 
+				HTMLPrinter.insertPageProlog(buffer, 0, fgRGB, bgRGB, getCSSStyles());
+				
 				buffer.append(info);
 
 				IJavaElement element= null;
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/AbstractAnnotationHover.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/AbstractAnnotationHover.java
index b86a83a..6c4f3d2 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/AbstractAnnotationHover.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/AbstractAnnotationHover.java
@@ -293,7 +293,10 @@
 			if (background == null) {
 				background= fParent.getBackground();
 			}
-			setColorAndFont(fParent, foreground, background, JFaceResources.getDialogFont());
+
+			setForegroundColor(foreground); // For main composite.
+			setBackgroundColor(background);
+			setColorAndFont(fParent, foreground, background, JFaceResources.getDialogFont()); // For child elements.
 
 			ICompletionProposal[] proposals= getAnnotationInfo().getCompletionProposals();
 			if (proposals.length > 0)
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavadocHover.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavadocHover.java
index 00cd885..8688709 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavadocHover.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/java/hover/JavadocHover.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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,11 +23,13 @@
 import org.osgi.framework.Bundle;
 
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.graphics.Drawable;
 import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.RGB;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.graphics.RGB;
 
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.OperationCanceledException;
@@ -44,6 +46,8 @@
 import org.eclipse.jface.internal.text.html.HTMLTextPresenter;
 import org.eclipse.jface.resource.ColorRegistry;
 import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
 import org.eclipse.jface.viewers.StructuredSelection;
 
 import org.eclipse.jface.text.AbstractReusableInformationControlCreator;
@@ -66,12 +70,15 @@
 import org.eclipse.ui.editors.text.EditorsUI;
 
 import org.eclipse.jdt.core.IAnnotatable;
+import org.eclipse.jdt.core.IAnnotation;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.ILocalVariable;
 import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IMemberValuePair;
+import org.eclipse.jdt.core.IMethod;
 import org.eclipse.jdt.core.IPackageDeclaration;
 import org.eclipse.jdt.core.IPackageFragment;
 import org.eclipse.jdt.core.IPackageFragmentRoot;
@@ -96,7 +103,9 @@
 import org.eclipse.jdt.core.dom.SimpleName;
 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
 
+import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
+import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
 import org.eclipse.jdt.internal.corext.javadoc.JavaDocLocations;
 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
 import org.eclipse.jdt.internal.corext.util.JdtFlags;
@@ -113,11 +122,10 @@
 import org.eclipse.jdt.internal.ui.actions.OpenBrowserUtil;
 import org.eclipse.jdt.internal.ui.actions.SimpleSelectionProvider;
 import org.eclipse.jdt.internal.ui.infoviews.JavadocView;
-import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
 import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
 import org.eclipse.jdt.internal.ui.packageview.PackageExplorerPart;
 import org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2;
-import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
+import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLabelComposer;
 import org.eclipse.jdt.internal.ui.viewsupport.JavaElementLinks;
 
 
@@ -378,7 +386,7 @@
 	 *
 	 * @since 3.3
 	 */
-	public static final class HoverControlCreator extends AbstractReusableInformationControlCreator {
+	public static final class HoverControlCreator extends AbstractReusableInformationControlCreator implements IPropertyChangeListener {
 		/**
 		 * The information presenter control creator.
 		 * @since 3.4
@@ -407,6 +415,7 @@
 			fAdditionalInfoAffordance= additionalInfoAffordance;
 		}
 
+		private BrowserInformationControl iControl;
 		/*
 		 * @see org.eclipse.jdt.internal.ui.text.java.hover.AbstractReusableInformationControlCreator#doCreateInformationControl(org.eclipse.swt.widgets.Shell)
 		 */
@@ -415,7 +424,7 @@
 			String tooltipAffordanceString= fAdditionalInfoAffordance ? JavaPlugin.getAdditionalInfoAffordanceString() : EditorsUI.getTooltipAffordanceString();
 			if (BrowserInformationControl.isAvailable(parent)) {
 				String font= PreferenceConstants.APPEARANCE_JAVADOC_FONT;
-				BrowserInformationControl iControl= new BrowserInformationControl(parent, font, tooltipAffordanceString) {
+				iControl= new BrowserInformationControl(parent, font, tooltipAffordanceString) {
 					/*
 					 * @see org.eclipse.jface.text.IInformationControlExtension5#getInformationPresenterControlCreator()
 					 */
@@ -424,6 +433,10 @@
 						return fInformationPresenterControlCreator;
 					}
 				};
+				
+				JFaceResources.getColorRegistry().addListener(this); // So propertyChange() method is triggered in context of IPropertyChangeListener
+				setHoverColors();
+				
 				addLinkListener(iControl);
 				return iControl;
 			} else {
@@ -441,6 +454,31 @@
 			}
 		}
 
+		@Override
+		public void propertyChange(PropertyChangeEvent event) {
+			String property= event.getProperty();
+			if (iControl != null &&
+					(property.equals("org.eclipse.jdt.ui.Javadoc.foregroundColor") //$NON-NLS-1$
+							|| property.equals("org.eclipse.jdt.ui.Javadoc.backgroundColor"))) { //$NON-NLS-1$
+				setHoverColors();
+			}
+		}
+		
+		private void setHoverColors() {
+			ColorRegistry registry = JFaceResources.getColorRegistry();
+			Color fgRGB = registry.get("org.eclipse.jdt.ui.Javadoc.foregroundColor"); //$NON-NLS-1$ 
+			Color bgRGB = registry.get("org.eclipse.jdt.ui.Javadoc.backgroundColor"); //$NON-NLS-1$ 
+			iControl.setForegroundColor(fgRGB);
+			iControl.setBackgroundColor(bgRGB);
+		}
+
+		@Override
+		public void widgetDisposed(DisposeEvent e) {
+			super.widgetDisposed(e);
+			//Called when active editor is closed.
+			JFaceResources.getColorRegistry().removeListener(this);
+		}
+
 		/*
 		 * @see org.eclipse.jdt.internal.ui.text.java.hover.AbstractReusableInformationControlCreator#canReuse(org.eclipse.jface.text.IInformationControl)
 		 */
@@ -786,15 +824,87 @@
 			}
 		}
 
-//		if (element.getElementType() == IJavaElement.METHOD) {
-//			IMethod method= (IMethod)element;
-//			//TODO: add default value for annotation type members, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=249016
-//		}
+		if (element.getElementType() == IJavaElement.METHOD) {
+			String defaultValue;
+			try {
+				defaultValue= getAnnotationMemberDefaultValue((IMethod) element, editorInputElement, hoverRegion);
+			} catch (JavaModelException e) {
+				defaultValue= null;
+			}
+			if (defaultValue != null) {
+				defaultValue= HTMLPrinter.convertToHTMLContentWithWhitespace(defaultValue);
+				label.append(CONSTANT_VALUE_SEPARATOR);
+				label.append(defaultValue);
+			}
+		}
 
 		return getImageAndLabel(element, allowImage, label.toString());
 	}
 
 	/**
+	 * Returns the default value of the given annotation type method.
+	 * 
+	 * @param method the method
+	 * @param editorInputElement the editor input element
+	 * @param hoverRegion the hover region in the editor
+	 * @return the default value of the given annotation type method or <code>null</code> if none
+	 * @throws JavaModelException if an exception occurs while accessing its default value
+	 */
+	public static String getAnnotationMemberDefaultValue(IMethod method, ITypeRoot editorInputElement, IRegion hoverRegion) throws JavaModelException {
+		IMemberValuePair memberValuePair= method.getDefaultValue();
+		if (memberValuePair == null) {
+			return null;
+		}
+
+		Object defaultValue= memberValuePair.getValue();
+		boolean isEmptyArray= defaultValue instanceof Object[] && ((Object[]) defaultValue).length == 0;
+		int valueKind= memberValuePair.getValueKind();
+
+		if (valueKind == IMemberValuePair.K_UNKNOWN && !isEmptyArray) {
+			IBinding binding= getHoveredNodeBinding(method, editorInputElement, hoverRegion);
+			if (binding instanceof IMethodBinding) {
+				Object value= ((IMethodBinding) binding).getDefaultValue();
+				StringBuffer buf= new StringBuffer();
+				try {
+					addValue(buf, value, false);
+				} catch (URISyntaxException e) {
+					// should not happen as links are not added
+				}
+				return buf.toString();
+			}
+
+		} else if (defaultValue != null) {
+			IAnnotation parentAnnotation= (IAnnotation) method.getAncestor(IJavaElement.ANNOTATION);
+			StringBuffer buf= new StringBuffer();
+			new JavaElementLabelComposer(buf).appendAnnotationValue(parentAnnotation, defaultValue, valueKind, LABEL_FLAGS);
+			return buf.toString();
+		}
+
+		return null;
+	}
+
+	private static IBinding getHoveredNodeBinding(IJavaElement element, ITypeRoot editorInputElement, IRegion hoverRegion) {
+		if (editorInputElement == null || hoverRegion == null) {
+			return null;
+		}
+		IBinding binding;
+		ASTNode node= getHoveredASTNode(editorInputElement, hoverRegion);
+		if (node == null) {
+			ASTParser p= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
+			p.setProject(element.getJavaProject());
+			p.setBindingsRecovery(true);
+			try {
+				binding= p.createBindings(new IJavaElement[] { element }, null)[0];
+			} catch (OperationCanceledException e) {
+				return null;
+			}
+		} else {
+			binding= resolveBinding(node);
+		}
+		return binding;
+	}
+
+	/**
 	 * Try to acquire a binding corresponding to the given element 
 	 * for more precise information about (type) annotations.
 	 *
@@ -1074,23 +1184,7 @@
 				return null;
 		}
 		
-		IBinding binding;
-		ASTNode node= getHoveredASTNode(editorInputElement, hoverRegion);
-		
-		if (node == null) {
-			ASTParser p= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
-			p.setProject(element.getJavaProject());
-			p.setBindingsRecovery(true);
-			try {
-				binding= p.createBindings(new IJavaElement[] { element }, null)[0];
-			} catch (OperationCanceledException e) {
-				return null;
-			}
-			
-		} else {
-			binding= resolveBinding(node);
-		}
-		
+		IBinding binding= getHoveredNodeBinding(element, editorInputElement, hoverRegion);
 		if (binding == null)
 			return null;
 		
@@ -1101,7 +1195,7 @@
 		StringBuffer buf= new StringBuffer();
 		for (int i= 0; i < annotations.length; i++) {
 			//TODO: skip annotations that don't have an @Documented annotation?
-			addAnnotation(buf, element, annotations[i]);
+			addAnnotation(buf, annotations[i], true);
 			buf.append("<br>"); //$NON-NLS-1$
 		}
 		
@@ -1147,14 +1241,14 @@
 		return null;
 	}
 
-	private static void addAnnotation(StringBuffer buf, IJavaElement element, IAnnotationBinding annotation) throws URISyntaxException {
+	private static void addAnnotation(StringBuffer buf, IAnnotationBinding annotation, boolean addLinks) throws URISyntaxException {
 		IJavaElement javaElement= annotation.getAnnotationType().getJavaElement();
 		buf.append('@');
-		if (javaElement != null) {
+		if (javaElement == null || !addLinks) {
+			buf.append(annotation.getName());
+		} else {
 			String uri= JavaElementLinks.createURI(JavaElementLinks.JAVADOC_SCHEME, javaElement);
 			addLink(buf, uri, annotation.getName());
-		} else {
-			buf.append(annotation.getName());
 		}
 		
 		IMemberValuePairBinding[] mvPairs= annotation.getDeclaredMemberValuePairs();
@@ -1165,21 +1259,25 @@
 					buf.append(JavaElementLabels.COMMA_STRING);
 				}
 				IMemberValuePairBinding mvPair= mvPairs[j];
-				String memberURI= JavaElementLinks.createURI(JavaElementLinks.JAVADOC_SCHEME, mvPair.getMethodBinding().getJavaElement());
-				addLink(buf, memberURI, mvPair.getName());
+				if (addLinks) {
+					String memberURI= JavaElementLinks.createURI(JavaElementLinks.JAVADOC_SCHEME, mvPair.getMethodBinding().getJavaElement());
+					addLink(buf, memberURI, mvPair.getName());
+				} else {
+					buf.append(mvPair.getName());
+				}
 				buf.append('=');
-				addValue(buf, element, mvPair.getValue());
+				addValue(buf, mvPair.getValue(), addLinks);
 			}
 			buf.append(')');
 		}
 	}
 
-	private static void addValue(StringBuffer buf, IJavaElement element, Object value) throws URISyntaxException {
+	private static void addValue(StringBuffer buf, Object value, boolean addLinks) throws URISyntaxException {
 		// Note: To be bug-compatible with Javadoc from Java 5/6/7, we currently don't escape HTML tags in String-valued annotations.
 		if (value instanceof ITypeBinding) {
 			ITypeBinding typeBinding= (ITypeBinding)value;
 			IJavaElement type= typeBinding.getJavaElement();
-			if (type == null) {
+			if (type == null || !addLinks) {
 				buf.append(typeBinding.getName());
 			} else {
 				String uri= JavaElementLinks.createURI(JavaElementLinks.JAVADOC_SCHEME, type);
@@ -1191,13 +1289,17 @@
 		} else if (value instanceof IVariableBinding) { // only enum constants
 			IVariableBinding variableBinding= (IVariableBinding)value;
 			IJavaElement variable= variableBinding.getJavaElement();
-			String uri= JavaElementLinks.createURI(JavaElementLinks.JAVADOC_SCHEME, variable);
-			String name= variable.getElementName();
-			addLink(buf, uri, name);
+			if (variable == null || !addLinks) {
+				buf.append(variableBinding.getName());
+			} else {
+				String uri= JavaElementLinks.createURI(JavaElementLinks.JAVADOC_SCHEME, variable);
+				String name= variable.getElementName();
+				addLink(buf, uri, name);
+			}
 				
 		} else if (value instanceof IAnnotationBinding) {
 			IAnnotationBinding annotationBinding= (IAnnotationBinding)value;
-			addAnnotation(buf, element, annotationBinding);
+			addAnnotation(buf, annotationBinding, addLinks);
 			
 		} else if (value instanceof String) {
 			buf.append(ASTNodes.getEscapedStringLiteral((String)value));
@@ -1212,7 +1314,7 @@
 				if (i > 0) {
 					buf.append(JavaElementLabels.COMMA_STRING);
 				}
-				addValue(buf, element, values[i]);
+				addValue(buf, values[i], addLinks);
 			}
 			buf.append('}');
 			
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLabelComposer.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLabelComposer.java
index a35fb4f..feaf81a 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLabelComposer.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/viewsupport/JavaElementLabelComposer.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 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
@@ -582,7 +582,7 @@
 		fBuffer.append(')');
 	}
 
-	private void appendAnnotationValue(IAnnotation annotation, Object value, int valueKind, long flags) throws JavaModelException {
+	public void appendAnnotationValue(IAnnotation annotation, Object value, int valueKind, long flags) throws JavaModelException {
 		// Note: To be bug-compatible with Javadoc from Java 5/6/7, we currently don't escape HTML tags in String-valued annotations.
 		if (value instanceof Object[]) {
 			fBuffer.append('{');