blob: 58e93fb5bf84f8840daf6c914a58b7629e3ad7ef [file] [log] [blame]
Stephan Herrmann0289ab52011-01-28 21:06:41 +00001/*******************************************************************************
2 * Copyright (c) 2011 GK Software AG 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
7 *
8 * Contributors:
9 * Stephan Herrmann - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.objectteams.internal.jdt.nullity.quickfix;
12
Stephan Herrmannd05aafb2011-01-30 16:47:43 +000013import static org.eclipse.objectteams.internal.jdt.nullity.IConstants.IProblem.DefiniteNullFromNonNullMethod;
14import static org.eclipse.objectteams.internal.jdt.nullity.IConstants.IProblem.PotentialNullFromNonNullMethod;
15
Stephan Herrmann0289ab52011-01-28 21:06:41 +000016import java.util.ArrayList;
17import java.util.Hashtable;
18import java.util.List;
19import java.util.Map;
20
21import org.eclipse.core.runtime.CoreException;
22import org.eclipse.jdt.core.ICompilationUnit;
23import org.eclipse.jdt.core.JavaCore;
24import org.eclipse.jdt.core.compiler.IProblem;
25import org.eclipse.jdt.core.dom.CompilationUnit;
Stephan Herrmannd05aafb2011-01-30 16:47:43 +000026import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
Stephan Herrmann0289ab52011-01-28 21:06:41 +000027import org.eclipse.jdt.internal.ui.fix.AbstractMultiFix;
28import org.eclipse.jdt.ui.cleanup.CleanUpRequirements;
29import org.eclipse.jdt.ui.cleanup.ICleanUpFix;
30import org.eclipse.jdt.ui.text.java.IProblemLocation;
31import org.eclipse.objectteams.internal.jdt.nullity.NullCompilerOptions;
32
33/**
34 * Cleanup for adding required null annotations.
35 *
36 * Crafted after the lead of Java50CleanUp
37 *
38 * @author stephan
39 */
40@SuppressWarnings({ "rawtypes", "restriction", "unchecked" })
41public class NullAnnotationsCleanUp extends AbstractMultiFix {
42
43 private QuickFixes master;
44
45 public NullAnnotationsCleanUp(Map<String, String> options, QuickFixes quickFixes) {
46 super(options);
47 this.master = quickFixes;
48 }
49
50 /**
51 * {@inheritDoc}
52 */
53 public CleanUpRequirements getRequirements() {
54 boolean requireAST= requireAST();
55 Map requiredOptions= requireAST ? getRequiredOptions() : null;
56 return new CleanUpRequirements(requireAST, false, false, requiredOptions);
57 }
58
59 private boolean requireAST() {
60 boolean addAnotations= isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS);
61
Stephan Herrmannd05aafb2011-01-30 16:47:43 +000062 return addAnotations &&
63 ( isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_RETURN_ANNOTATION_NULLABLE)
64 || isEnabled(CleanUpConstants.ADD_POTENTIALLY_MISSING_RETURN_ANNOTATION_NULLABLE)
65 || isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_PARAMETER_ANNOTATION_NULLABLE));
Stephan Herrmann0289ab52011-01-28 21:06:41 +000066 }
67
68 /**
69 * {@inheritDoc}
70 */
71 protected ICleanUpFix createFix(CompilationUnit compilationUnit) throws CoreException {
Stephan Herrmannd05aafb2011-01-30 16:47:43 +000072 return this.createFix(compilationUnit, null);
Stephan Herrmann0289ab52011-01-28 21:06:41 +000073 }
74
75 /**
76 * {@inheritDoc}
77 */
78 protected ICleanUpFix createFix(CompilationUnit compilationUnit, IProblemLocation[] problems) throws CoreException {
79 if (compilationUnit == null)
80 return null;
81
82 boolean addAnnotations= isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS);
Stephan Herrmannd05aafb2011-01-30 16:47:43 +000083 boolean addDefintelyMissingReturnNullable = isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_RETURN_ANNOTATION_NULLABLE);
84 boolean addPotentiallyMissingReturnNullable = isEnabled(CleanUpConstants.ADD_POTENTIALLY_MISSING_RETURN_ANNOTATION_NULLABLE);
85 boolean addDefintelyMissingParamNullable = isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_PARAMETER_ANNOTATION_NULLABLE);
86 return this.master.createCleanUp(compilationUnit,
87 addAnnotations && addDefintelyMissingReturnNullable,
88 addAnnotations && addPotentiallyMissingReturnNullable,
89 addAnnotations && addDefintelyMissingParamNullable,
90 problems);
Stephan Herrmann0289ab52011-01-28 21:06:41 +000091 }
92
93 private Map getRequiredOptions() {
94 Map result= new Hashtable();
Stephan Herrmannd05aafb2011-01-30 16:47:43 +000095 if (isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS) &&
96 ( isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_RETURN_ANNOTATION_NULLABLE)
97 || isEnabled(CleanUpConstants.ADD_POTENTIALLY_MISSING_RETURN_ANNOTATION_NULLABLE)
98 || isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_PARAMETER_ANNOTATION_NULLABLE)))
99 {
Stephan Herrmann0289ab52011-01-28 21:06:41 +0000100 result.put(NullCompilerOptions.OPTION_ReportNullContractViolation, JavaCore.WARNING);
Stephan Herrmannd05aafb2011-01-30 16:47:43 +0000101 result.put(CompilerOptions.OPTION_ReportRedundantNullCheck, JavaCore.WARNING);
Stephan Herrmann0289ab52011-01-28 21:06:41 +0000102 }
103 return result;
104 }
105
106 /**
107 * {@inheritDoc}
108 */
109 public String[] getStepDescriptions() {
110 List result= new ArrayList();
Stephan Herrmannd05aafb2011-01-30 16:47:43 +0000111 if (isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS) &&
112 ( isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_RETURN_ANNOTATION_NULLABLE)
113 || isEnabled(CleanUpConstants.ADD_POTENTIALLY_MISSING_RETURN_ANNOTATION_NULLABLE)
114 || isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_PARAMETER_ANNOTATION_NULLABLE)))
115 {
Stephan Herrmann0289ab52011-01-28 21:06:41 +0000116 result.add(FixMessages.NullAnnotationsCleanUp_add_nullable_annotation);
117 }
118 return (String[])result.toArray(new String[result.size()]);
119 }
120
121 /**
122 * {@inheritDoc}
123 */
124 public String getPreview() {
125 StringBuffer buf= new StringBuffer();
126
127 buf.append("class E {\n"); //$NON-NLS-1$
Stephan Herrmannd05aafb2011-01-30 16:47:43 +0000128 if (isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS) &&
129 ( isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_RETURN_ANNOTATION_NULLABLE)
130 || isEnabled(CleanUpConstants.ADD_POTENTIALLY_MISSING_RETURN_ANNOTATION_NULLABLE)
131 || isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_PARAMETER_ANNOTATION_NULLABLE)))
132 {
Stephan Herrmann0289ab52011-01-28 21:06:41 +0000133 buf.append(" @Nullable\n"); //$NON-NLS-1$
134 }
135 buf.append(" public Object foo() { return null; }\n"); //$NON-NLS-1$
136 buf.append("}\n"); //$NON-NLS-1$
137
138 return buf.toString();
139 }
140
141 /**
142 * {@inheritDoc}
143 */
144 public boolean canFix(ICompilationUnit compilationUnit, IProblemLocation problem) {
145 int id= problem.getProblemId();
146
Stephan Herrmannd05aafb2011-01-30 16:47:43 +0000147 if (QuickFixes.isMissingNullableAnnotationProblem(id)) {
148 if ( isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS)
149 && ( ((id == DefiniteNullFromNonNullMethod) && isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_RETURN_ANNOTATION_NULLABLE))
150 || ((id == PotentialNullFromNonNullMethod) && isEnabled(CleanUpConstants.ADD_POTENTIALLY_MISSING_RETURN_ANNOTATION_NULLABLE))
151 || ((id == IProblem.NonNullLocalVariableComparisonYieldsFalse) && isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_PARAMETER_ANNOTATION_NULLABLE))))
152 {
153 // FIXME search specifically: return param (which??)
154// if (QuickFixes.hasExplicitNullnessAnnotation(compilationUnit, problem.getOffset()))
155// return false;
Stephan Herrmann0289ab52011-01-28 21:06:41 +0000156 return true;
157 }
158 }
159
160 return false;
161 }
162
163
164 /**
165 * {@inheritDoc}
166 */
167 public int computeNumberOfFixes(CompilationUnit compilationUnit) {
Stephan Herrmann0289ab52011-01-28 21:06:41 +0000168 int result= 0;
169
170 boolean addAnnotations= isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS);
Stephan Herrmannd05aafb2011-01-30 16:47:43 +0000171 boolean addDefinitelyMissingReturnNullable= addAnnotations && isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_RETURN_ANNOTATION_NULLABLE);
172 boolean addPotentiallyMissingReturnNullable= addAnnotations && isEnabled(CleanUpConstants.ADD_POTENTIALLY_MISSING_RETURN_ANNOTATION_NULLABLE);
173 boolean addDefinitelyMissingParamNullable= addAnnotations && isEnabled(CleanUpConstants.ADD_DEFINITELY_MISSING_PARAMETER_ANNOTATION_NULLABLE);
Stephan Herrmann0289ab52011-01-28 21:06:41 +0000174
175 IProblem[] problems= compilationUnit.getProblems();
176 for (int i= 0; i < problems.length; i++) {
177 int id= problems[i].getID();
Stephan Herrmannd05aafb2011-01-30 16:47:43 +0000178 if ( (addDefinitelyMissingReturnNullable && id == DefiniteNullFromNonNullMethod)
179 || (addPotentiallyMissingReturnNullable && id == PotentialNullFromNonNullMethod)
180 || (addDefinitelyMissingParamNullable && id == IProblem.NonNullLocalVariableComparisonYieldsFalse))
181 if (!QuickFixes.hasExplicitNullnessAnnotation((ICompilationUnit) compilationUnit.getJavaElement(), problems[i].getSourceStart()))
Stephan Herrmann0289ab52011-01-28 21:06:41 +0000182 result++;
183 }
184 return result;
185 }
186}