Bug 181788: [quick fix] Quick fix to import static from favorite class
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/UnresolvedMethodsQuickFixTest.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/UnresolvedMethodsQuickFixTest.java
index 92cc444..d4804a5 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/UnresolvedMethodsQuickFixTest.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/UnresolvedMethodsQuickFixTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -4864,6 +4864,83 @@
 
 		assertExpectedExistInProposals(proposals, expected);
 	}
+	
+	public void testStaticImportFavorite1() throws Exception {
+		IPreferenceStore preferenceStore= PreferenceConstants.getPreferenceStore();
+		preferenceStore.setValue(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, "java.lang.Math.*");
+		try {		
+			IPackageFragment pack1= fSourceFolder.createPackageFragment("pack", false, null);
+			StringBuffer buf= new StringBuffer();
+			buf.append("package pack;\n");
+			buf.append("\n");
+			buf.append("public class E {\n");
+			buf.append("    private int foo() {\n");
+			buf.append("        return max(1, 2);\n");
+			buf.append("    }\n");
+			buf.append("}\n");
+			ICompilationUnit cu= pack1.createCompilationUnit("E.java", buf.toString(), false, null);
+	
+			CompilationUnit astRoot= getASTRoot(cu);
+			ArrayList proposals= collectCorrections(cu, astRoot);
+	
+			assertCorrectLabels(proposals);
+	
+			String[] expected= new String[1];
+			buf= new StringBuffer();
+			buf.append("package pack;\n");
+			buf.append("\n");
+			buf.append("import static java.lang.Math.max;\n");
+			buf.append("\n");
+			buf.append("public class E {\n");
+			buf.append("    private int foo() {\n");
+			buf.append("        return max(1, 2);\n");
+			buf.append("    }\n");
+			buf.append("}\n");
+			expected[0]= buf.toString();
+	
+			assertExpectedExistInProposals(proposals, expected);
+		} finally {
+			preferenceStore.setValue(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, "");
+		}
+	}
+	
+	public void testStaticImportFavorite2() throws Exception {
+		IPreferenceStore preferenceStore= PreferenceConstants.getPreferenceStore();
+		preferenceStore.setValue(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, "java.lang.Math.max");
+		try {		
+			IPackageFragment pack1= fSourceFolder.createPackageFragment("pack", false, null);
+			StringBuffer buf= new StringBuffer();
+			buf.append("package pack;\n");
+			buf.append("\n");
+			buf.append("public class E {\n");
+			buf.append("    private int max() {\n");
+			buf.append("        return max(1, 2);\n");
+			buf.append("    }\n");
+			buf.append("}\n");
+			ICompilationUnit cu= pack1.createCompilationUnit("E.java", buf.toString(), false, null);
+	
+			CompilationUnit astRoot= getASTRoot(cu);
+			ArrayList proposals= collectCorrections(cu, astRoot);
+	
+			assertCorrectLabels(proposals);
+	
+			String[] expected= new String[1];
+			buf= new StringBuffer();
+			buf.append("package pack;\n");
+			buf.append("\n");
+			buf.append("public class E {\n");
+			buf.append("    private int max() {\n");
+			buf.append("        return Math.max(1, 2);\n"); // naming conflict
+			buf.append("    }\n");
+			buf.append("}\n");
+			expected[0]= buf.toString();
+	
+			assertExpectedExistInProposals(proposals, expected);
+		} finally {
+			preferenceStore.setValue(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, "");
+		}
+	}
+
 
 
 }
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/UnresolvedVariablesQuickFixTest.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/UnresolvedVariablesQuickFixTest.java
index a7139d5..72bdb7a 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/UnresolvedVariablesQuickFixTest.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/UnresolvedVariablesQuickFixTest.java
@@ -1459,7 +1459,44 @@
 		assertExpectedExistInProposals(proposals, expected);
 	}
 
-
+	public void testStaticImportFavorite1() throws Exception {
+		IPreferenceStore preferenceStore= PreferenceConstants.getPreferenceStore();
+		preferenceStore.setValue(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, "java.lang.Math.*");
+		try {		
+			IPackageFragment pack1= fSourceFolder.createPackageFragment("pack", false, null);
+			StringBuffer buf= new StringBuffer();
+			buf.append("package pack;\n");
+			buf.append("\n");
+			buf.append("public class E {\n");
+			buf.append("    private float foo() {\n");
+			buf.append("        return PI;\n");
+			buf.append("    }\n");
+			buf.append("}\n");
+			ICompilationUnit cu= pack1.createCompilationUnit("E.java", buf.toString(), false, null);
+	
+			CompilationUnit astRoot= getASTRoot(cu);
+			ArrayList proposals= collectCorrections(cu, astRoot);
+	
+			assertCorrectLabels(proposals);
+	
+			String[] expected= new String[1];
+			buf= new StringBuffer();
+			buf.append("package pack;\n");
+			buf.append("\n");
+			buf.append("import static java.lang.Math.PI;\n");
+			buf.append("\n");
+			buf.append("public class E {\n");
+			buf.append("    private float foo() {\n");
+			buf.append("        return PI;\n");
+			buf.append("    }\n");
+			buf.append("}\n");
+			expected[0]= buf.toString();
+	
+			assertExpectedExistInProposals(proposals, expected);
+		} finally {
+			preferenceStore.setValue(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, "");
+		}
+	}
 
 	public void testLongVarRef() throws Exception {
 		IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.java
index 3163b3d..c2fe3cf 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 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
@@ -166,6 +166,7 @@
 	public static String UnresolvedElementsSubProcessor_swaparguments_description;
 	public static String UnresolvedElementsSubProcessor_add_annotation_bundle_description;
 	public static String UnresolvedElementsSubProcessor_add_annotation_bundle_info;
+	public static String UnresolvedElementsSubProcessor_add_static_import_description;
 	public static String UnresolvedElementsSubProcessor_addargumentcast_description;
 	public static String UnresolvedElementsSubProcessor_changemethod_description;
 	public static String UnresolvedElementsSubProcessor_changetoouter_description;
@@ -344,6 +345,7 @@
 	public static String ReorgCorrectionsSubProcessor_50_compliance_changeWorkspaceJRE_description;
 	public static String ReorgCorrectionsSubProcessor_50_compliance_changeProjectJRE_description;
 	public static String ModifierCorrectionSubProcessor_default_visibility_label;
+	public static String UnresolvedElementsSubProcessor_change_to_static_import_description;
 	public static String ReorgCorrectionsSubProcessor_configure_buildpath_label;
 	public static String ReorgCorrectionsSubProcessor_configure_buildpath_description;
 	public static String QuickAssistProcessor_extract_to_local_all_description;
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties
index b3ca9fc..ba45185 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/CorrectionMessages.properties
@@ -183,6 +183,7 @@
 UnresolvedElementsSubProcessor_swaparguments_description=Swap arguments {0} and {1}
 UnresolvedElementsSubProcessor_add_annotation_bundle_description=Add 'org.eclipse.jdt.annotation' to build path
 UnresolvedElementsSubProcessor_add_annotation_bundle_info=Adds this line to 'build.properties':
+UnresolvedElementsSubProcessor_add_static_import_description=Add static import for ''{0}''
 UnresolvedElementsSubProcessor_addargumentcast_description=Cast argument {0} to ''{1}''
 UnresolvedElementsSubProcessor_changemethod_description=Change to ''{0}(..)''
 UnresolvedElementsSubProcessor_changetoouter_description=Qualify with enclosing type ''{0}''
@@ -194,6 +195,7 @@
 UnresolvedElementsSubProcessor_changetype_description=Change to ''{0}'' ({1})
 UnresolvedElementsSubProcessor_changetype_nopack_description=Change to ''{0}''
 UnresolvedElementsSubProcessor_change_full_type_description=Change type to ''{0}''
+UnresolvedElementsSubProcessor_change_to_static_import_description=Change to ''{0}''
 UnresolvedElementsSubProcessor_importtype_description=Import ''{0}'' ({1})
 
 UnresolvedElementsSubProcessor_changevariable_description=Change to ''{0}''
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/SimilarElementsRequestor.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/SimilarElementsRequestor.java
index 9c99ff2..976b374 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/SimilarElementsRequestor.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/SimilarElementsRequestor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2011 IBM Corporation and others.
+ * Copyright (c) 2000, 2012 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -16,6 +16,7 @@
 import org.eclipse.jdt.core.CompletionRequestor;
 import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.dom.ASTNode;
@@ -25,6 +26,7 @@
 import org.eclipse.jdt.core.dom.QualifiedName;
 
 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
+import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
 import org.eclipse.jdt.internal.corext.util.TypeFilter;
 
 public class SimilarElementsRequestor extends CompletionRequestor {
@@ -210,4 +212,62 @@
 			addType(proposal.getSignature(), proposal.getFlags(), proposal.getRelevance());
 		}
 	}
+	
+	
+	public static String[] getStaticImportFavorites(ICompilationUnit cu, final String elementName, boolean isMethod, String[] favorites) throws JavaModelException {
+		StringBuffer dummyCU= new StringBuffer();
+		String packName= cu.getParent().getElementName();
+		IType type= cu.findPrimaryType();
+		if (type == null)
+			return new String[0];
+		
+		if (packName.length() > 0) {
+			dummyCU.append("package ").append(packName).append(';'); //$NON-NLS-1$
+		}		
+		dummyCU.append("public class ").append(type.getElementName()).append("{\n static {\n").append(elementName); // static initializer  //$NON-NLS-1$//$NON-NLS-2$
+		int offset= dummyCU.length();
+		dummyCU.append("\n}\n }"); //$NON-NLS-1$
+		
+		ICompilationUnit newCU= null;
+		try {
+			newCU= cu.getWorkingCopy(null);
+			newCU.getBuffer().setContents(dummyCU.toString());
+			
+			final HashSet<String> result= new HashSet<String>();
+			
+			CompletionRequestor requestor= new CompletionRequestor(true) {
+				@Override
+				public void accept(CompletionProposal proposal) {
+					if (elementName.equals(new String(proposal.getName()))) {
+						CompletionProposal[] requiredProposals= proposal.getRequiredProposals();
+						for (int i= 0; i < requiredProposals.length; i++) {
+							CompletionProposal curr= requiredProposals[i];
+							if (curr.getKind() == CompletionProposal.METHOD_IMPORT || curr.getKind() == CompletionProposal.FIELD_IMPORT) {
+								result.add(JavaModelUtil.concatenateName(Signature.toCharArray(curr.getDeclarationSignature()), curr.getName()));
+							}
+						}
+					}
+				}
+			};
+			
+			if (isMethod) {
+				requestor.setIgnored(CompletionProposal.METHOD_REF, false);
+				requestor.setAllowsRequiredProposals(CompletionProposal.METHOD_REF, CompletionProposal.METHOD_IMPORT, true);
+			} else {
+				requestor.setIgnored(CompletionProposal.FIELD_REF, false);
+				requestor.setAllowsRequiredProposals(CompletionProposal.FIELD_REF, CompletionProposal.FIELD_IMPORT, true);
+			}
+			requestor.setFavoriteReferences(favorites);
+			
+			newCU.codeComplete(offset, requestor);
+			
+			return result.toArray(new String[result.size()]);
+		} finally {
+			if (newCU != null) {
+				newCU.discardWorkingCopy();
+			}	
+		}	
+	}
+
+	
 }
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/UnresolvedElementsSubProcessor.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/UnresolvedElementsSubProcessor.java
index 781681e..8f9cd6f 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/UnresolvedElementsSubProcessor.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/UnresolvedElementsSubProcessor.java
@@ -128,6 +128,7 @@
 
 import org.eclipse.jdt.ui.JavaElementImageDescriptor;
 import org.eclipse.jdt.ui.JavaElementLabels;
+import org.eclipse.jdt.ui.PreferenceConstants;
 import org.eclipse.jdt.ui.text.java.IInvocationContext;
 import org.eclipse.jdt.ui.text.java.IProblemLocation;
 import org.eclipse.jdt.ui.text.java.correction.ASTRewriteCorrectionProposal;
@@ -293,6 +294,10 @@
 
 		// similar variables
 		addSimilarVariableProposals(cu, astRoot, binding, simpleName, isWriteAccess, proposals);
+		
+		if (binding == null) {
+			addStaticImportFavoriteProposals(context, simpleName, false, proposals);
+		}
 
 		if (resolvedField == null || binding == null || resolvedField.getDeclaringClass() != binding.getTypeDeclaration() && Modifier.isPrivate(resolvedField.getModifiers())) {
 
@@ -1056,6 +1061,10 @@
 			}
 			addParameterMissmatchProposals(context, problem, parameterMismatchs, invocationNode, arguments, proposals);
 		}
+		
+		if (sender == null) {
+			addStaticImportFavoriteProposals(context, nameNode, true, proposals);
+		}
 
 		// new method
 		addNewMethodProposals(cu, astRoot, sender, arguments, isSuperInvocation, invocationNode, methodName, proposals);
@@ -1073,6 +1082,50 @@
 		}
 
 	}
+	
+	private static void addStaticImportFavoriteProposals(IInvocationContext context, SimpleName node, boolean isMethod, Collection<ICommandAccess> proposals) throws JavaModelException {
+		IJavaProject project= context.getCompilationUnit().getJavaProject();
+		if (JavaModelUtil.is50OrHigher(project)) {
+			String pref= PreferenceConstants.getPreference(PreferenceConstants.CODEASSIST_FAVORITE_STATIC_MEMBERS, project);
+			String[] favourites= pref.split(";"); //$NON-NLS-1$
+			if (favourites.length == 0) {
+				return;
+			}
+
+			CompilationUnit root= context.getASTRoot();
+			AST ast= root.getAST();
+			
+			String name= node.getIdentifier();
+			String[] staticImports= SimilarElementsRequestor.getStaticImportFavorites(context.getCompilationUnit(), name, isMethod, favourites);
+			for (int i= 0; i < staticImports.length; i++) {
+				String curr= staticImports[i];
+				
+				ImportRewrite importRewrite= StubUtility.createImportRewrite(root, true);
+				ASTRewrite astRewrite= ASTRewrite.create(ast);
+				
+				String label;
+				String qualifiedTypeName= Signature.getQualifier(curr);
+				String elementLabel= BasicElementLabels.getJavaElementName(JavaModelUtil.concatenateName(Signature.getSimpleName(qualifiedTypeName), name));
+				
+				String res= importRewrite.addStaticImport(qualifiedTypeName, name, isMethod, new ContextSensitiveImportRewriteContext(root, node.getStartPosition(), importRewrite));
+				int dot= res.lastIndexOf('.');
+				if (dot != -1) {
+					String usedTypeName= importRewrite.addImport(qualifiedTypeName);
+					Name newName= ast.newQualifiedName(ast.newName(usedTypeName), ast.newSimpleName(name));
+					astRewrite.replace(node, newName, null);
+					label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_change_to_static_import_description, elementLabel);
+				} else {
+					label= Messages.format(CorrectionMessages.UnresolvedElementsSubProcessor_add_static_import_description, elementLabel);
+				}
+
+				Image image= JavaPluginImages.get(JavaPluginImages.IMG_OBJS_IMPDECL);
+				ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), astRewrite, 5, image);
+				proposal.setImportRewrite(importRewrite);
+				proposals.add(proposal);
+			}
+		}
+	}
+	
 
 	private static void addNewMethodProposals(ICompilationUnit cu, CompilationUnit astRoot, Expression sender, List<Expression> arguments, boolean isSuperInvocation, ASTNode invocationNode, String methodName, Collection<ICommandAccess> proposals) throws JavaModelException {
 		ITypeBinding nodeParentType= Bindings.getBindingOfParentType(invocationNode);