1 /*******************************************************************************
2 * Copyright (c) 2000, 2011 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.internal.ui.fix;
13 import java.util.ArrayList;
14 import java.util.Hashtable;
15 import java.util.List;
18 import org.eclipse.core.runtime.CoreException;
20 import org.eclipse.jdt.core.ICompilationUnit;
21 import org.eclipse.jdt.core.JavaCore;
22 import org.eclipse.jdt.core.compiler.IProblem;
23 import org.eclipse.jdt.core.dom.CompilationUnit;
25 import org.eclipse.jdt.internal.corext.fix.CleanUpConstants;
26 import org.eclipse.jdt.internal.corext.fix.CodeStyleFix;
28 import org.eclipse.jdt.ui.cleanup.CleanUpRequirements;
29 import org.eclipse.jdt.ui.cleanup.ICleanUpFix;
30 import org.eclipse.jdt.ui.text.java.IProblemLocation;
33 * Creates fixes which can resolve code style issues
34 * @see org.eclipse.jdt.internal.corext.fix.CodeStyleFix
36 public class CodeStyleCleanUp extends AbstractMultiFix {
38 public CodeStyleCleanUp() {
41 public CodeStyleCleanUp(Map<String, String> options) {
49 public CleanUpRequirements getRequirements() {
50 boolean requireAST= requireAST();
51 Map<String, String> requiredOptions= requireAST ? getRequiredOptions() : null;
52 return new CleanUpRequirements(requireAST, false, false, requiredOptions);
55 private boolean requireAST() {
56 boolean nonStaticFields= isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS);
57 boolean nonStaticMethods= isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS);
58 boolean qualifyStatic= isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS);
60 return nonStaticFields && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS_ALWAYS) ||
61 qualifyStatic && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_INSTANCE_ACCESS) ||
62 qualifyStatic && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_FIELD) ||
63 qualifyStatic && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_SUBTYPE_ACCESS) ||
64 nonStaticMethods && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS_ALWAYS) ||
65 qualifyStatic && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_METHOD) ||
66 nonStaticFields && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS_IF_NECESSARY) ||
67 nonStaticMethods && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS_IF_NECESSARY);
74 protected ICleanUpFix createFix(CompilationUnit compilationUnit) throws CoreException {
75 if (compilationUnit == null)
78 boolean nonStaticFields= isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS);
79 boolean nonStaticMethods= isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS);
80 boolean qualifyStatic= isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS);
82 return CodeStyleFix.createCleanUp(compilationUnit,
83 nonStaticFields && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS_ALWAYS),
84 qualifyStatic && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_INSTANCE_ACCESS),
85 qualifyStatic && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_FIELD),
86 qualifyStatic && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_SUBTYPE_ACCESS),
87 nonStaticMethods && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS_ALWAYS),
88 qualifyStatic && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_METHOD),
89 nonStaticFields && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS_IF_NECESSARY),
90 nonStaticMethods && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS_IF_NECESSARY)
99 protected ICleanUpFix createFix(CompilationUnit compilationUnit, IProblemLocation[] problems) throws CoreException {
100 return CodeStyleFix.createCleanUp(compilationUnit, problems,
101 isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS_ALWAYS),
102 isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_INSTANCE_ACCESS),
103 isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_SUBTYPE_ACCESS));
106 private Map<String, String> getRequiredOptions() {
107 Map<String, String> result= new Hashtable<String, String>();
108 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_INSTANCE_ACCESS))
109 result.put(JavaCore.COMPILER_PB_STATIC_ACCESS_RECEIVER, JavaCore.WARNING);
110 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_SUBTYPE_ACCESS))
111 result.put(JavaCore.COMPILER_PB_INDIRECT_STATIC_ACCESS, JavaCore.WARNING);
119 public String[] getStepDescriptions() {
120 List<String> result= new ArrayList<String>();
121 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS_ALWAYS))
122 result.add(MultiFixMessages.CodeStyleMultiFix_AddThisQualifier_description);
123 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS_ALWAYS))
124 result.add(MultiFixMessages.CodeStyleCleanUp_QualifyNonStaticMethod_description);
125 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS_IF_NECESSARY))
126 result.add(MultiFixMessages.CodeStyleCleanUp_removeFieldThis_description);
127 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS_IF_NECESSARY))
128 result.add(MultiFixMessages.CodeStyleCleanUp_removeMethodThis_description);
129 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_FIELD))
130 result.add(MultiFixMessages.CodeStyleMultiFix_QualifyAccessToStaticField);
131 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_METHOD))
132 result.add(MultiFixMessages.CodeStyleCleanUp_QualifyStaticMethod_description);
133 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_INSTANCE_ACCESS))
134 result.add(MultiFixMessages.CodeStyleMultiFix_ChangeNonStaticAccess_description);
135 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_SUBTYPE_ACCESS))
136 result.add(MultiFixMessages.CodeStyleMultiFix_ChangeIndirectAccessToStaticToDirect);
137 return result.toArray(new String[result.size()]);
141 public String getPreview() {
142 StringBuffer buf= new StringBuffer();
144 buf.append("private int value;\n"); //$NON-NLS-1$
145 buf.append("public int get() {\n"); //$NON-NLS-1$
146 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS_ALWAYS)) {
147 buf.append(" return this.value + this.value;\n"); //$NON-NLS-1$
148 } else if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS_IF_NECESSARY)) {
149 buf.append(" return value + value;\n"); //$NON-NLS-1$
151 buf.append(" return this.value + value;\n"); //$NON-NLS-1$
153 buf.append("}\n"); //$NON-NLS-1$
154 buf.append("\n"); //$NON-NLS-1$
155 buf.append("public int getZero() {\n"); //$NON-NLS-1$
156 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS_ALWAYS)) {
157 buf.append(" return this.get() - this.get();\n"); //$NON-NLS-1$
158 } else if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_METHOD_USE_THIS_IF_NECESSARY)) {
159 buf.append(" return get() - get();\n"); //$NON-NLS-1$
161 buf.append(" return this.get() - get();\n"); //$NON-NLS-1$
163 buf.append("}\n"); //$NON-NLS-1$
164 buf.append("\n"); //$NON-NLS-1$
165 buf.append("class E {\n"); //$NON-NLS-1$
166 buf.append(" public static int NUMBER;\n"); //$NON-NLS-1$
167 buf.append(" public static void set(int i) {\n"); //$NON-NLS-1$
168 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_FIELD)) {
169 buf.append(" E.NUMBER= i;\n"); //$NON-NLS-1$
171 buf.append(" NUMBER= i;\n"); //$NON-NLS-1$
173 buf.append(" }\n"); //$NON-NLS-1$
174 buf.append("\n"); //$NON-NLS-1$
175 buf.append(" public void reset() {\n"); //$NON-NLS-1$
176 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_METHOD)) {
177 buf.append(" E.set(0);\n"); //$NON-NLS-1$
179 buf.append(" set(0);\n"); //$NON-NLS-1$
181 buf.append(" }\n"); //$NON-NLS-1$
182 buf.append("}\n"); //$NON-NLS-1$
183 buf.append("\n"); //$NON-NLS-1$
184 buf.append("class ESub extends E {\n"); //$NON-NLS-1$
185 buf.append(" public void reset() {\n"); //$NON-NLS-1$
186 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_SUBTYPE_ACCESS)) {
187 buf.append(" E.NUMBER= 0;\n"); //$NON-NLS-1$
189 buf.append(" ESub.NUMBER= 0;\n"); //$NON-NLS-1$
191 buf.append(" }\n"); //$NON-NLS-1$
192 buf.append("}\n"); //$NON-NLS-1$
193 buf.append("\n"); //$NON-NLS-1$
194 buf.append("public void dec() {\n"); //$NON-NLS-1$
195 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_INSTANCE_ACCESS)) {
196 buf.append(" E.NUMBER--;\n"); //$NON-NLS-1$
198 buf.append(" (new E()).NUMBER--;\n"); //$NON-NLS-1$
200 buf.append("}\n"); //$NON-NLS-1$
202 return buf.toString();
208 public boolean canFix(ICompilationUnit compilationUnit, IProblemLocation problem) {
209 if (IProblem.UnqualifiedFieldAccess == problem.getProblemId())
210 return isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS_ALWAYS);
212 if (CodeStyleFix.isIndirectStaticAccess(problem))
213 return isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_SUBTYPE_ACCESS);
215 if (CodeStyleFix.isNonStaticAccess(problem))
216 return isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_INSTANCE_ACCESS);
225 public int computeNumberOfFixes(CompilationUnit compilationUnit) {
227 IProblem[] problems= compilationUnit.getProblems();
228 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_NON_STATIC_FIELD_USE_THIS_ALWAYS))
229 result+= getNumberOfProblems(problems, IProblem.UnqualifiedFieldAccess);
230 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_SUBTYPE_ACCESS)) {
231 for (int i=0;i<problems.length;i++) {
232 int id= problems[i].getID();
233 if (id == IProblem.IndirectAccessToStaticField || id == IProblem.IndirectAccessToStaticMethod)
237 if (isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS) && isEnabled(CleanUpConstants.MEMBER_ACCESSES_STATIC_QUALIFY_WITH_DECLARING_CLASS_INSTANCE_ACCESS)) {
238 for (int i=0;i<problems.length;i++) {
239 int id= problems[i].getID();
240 if (id == IProblem.NonStaticAccessToStaticField || id == IProblem.NonStaticAccessToStaticMethod)