blob: 32a4c7c0980147a099aeab69d7eb54272a6e6873 [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
13import java.util.ArrayList;
14import java.util.Hashtable;
15import java.util.List;
16import java.util.Map;
17
18import org.eclipse.core.runtime.CoreException;
19import org.eclipse.jdt.core.ICompilationUnit;
20import org.eclipse.jdt.core.JavaCore;
21import org.eclipse.jdt.core.compiler.IProblem;
22import org.eclipse.jdt.core.dom.CompilationUnit;
23import org.eclipse.jdt.internal.ui.fix.AbstractMultiFix;
24import org.eclipse.jdt.ui.cleanup.CleanUpRequirements;
25import org.eclipse.jdt.ui.cleanup.ICleanUpFix;
26import org.eclipse.jdt.ui.text.java.IProblemLocation;
27import org.eclipse.objectteams.internal.jdt.nullity.NullCompilerOptions;
28
29/**
30 * Cleanup for adding required null annotations.
31 *
32 * Crafted after the lead of Java50CleanUp
33 *
34 * @author stephan
35 */
36@SuppressWarnings({ "rawtypes", "restriction", "unchecked" })
37public class NullAnnotationsCleanUp extends AbstractMultiFix {
38
39 private QuickFixes master;
40
41 public NullAnnotationsCleanUp(Map<String, String> options, QuickFixes quickFixes) {
42 super(options);
43 this.master = quickFixes;
44 }
45
46 /**
47 * {@inheritDoc}
48 */
49 public CleanUpRequirements getRequirements() {
50 boolean requireAST= requireAST();
51 Map requiredOptions= requireAST ? getRequiredOptions() : null;
52 return new CleanUpRequirements(requireAST, false, false, requiredOptions);
53 }
54
55 private boolean requireAST() {
56 boolean addAnotations= isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS);
57
58 return addAnotations && isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS_NULLABLE);
59 }
60
61 /**
62 * {@inheritDoc}
63 */
64 protected ICleanUpFix createFix(CompilationUnit compilationUnit) throws CoreException {
65 if (compilationUnit == null)
66 return null;
67
68 boolean addAnotations= isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS);
69 boolean addNullable= isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS_NULLABLE);
70 return this.master.createCleanUp(compilationUnit, addAnotations && addNullable, null);
71 }
72
73 /**
74 * {@inheritDoc}
75 */
76 protected ICleanUpFix createFix(CompilationUnit compilationUnit, IProblemLocation[] problems) throws CoreException {
77 if (compilationUnit == null)
78 return null;
79
80 boolean addAnnotations= isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS);
81 boolean addNullable = isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS_NULLABLE);
82 return this.master.createCleanUp(compilationUnit, addAnnotations && addNullable, problems);
83 }
84
85 private Map getRequiredOptions() {
86 Map result= new Hashtable();
87 if (isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS) && isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS_NULLABLE)) {
88 result.put(NullCompilerOptions.OPTION_ReportNullContractViolation, JavaCore.WARNING);
89 }
90 return result;
91 }
92
93 /**
94 * {@inheritDoc}
95 */
96 public String[] getStepDescriptions() {
97 List result= new ArrayList();
98 if (isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS) && isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS_NULLABLE)) {
99 result.add(FixMessages.NullAnnotationsCleanUp_add_nullable_annotation);
100 }
101 return (String[])result.toArray(new String[result.size()]);
102 }
103
104 /**
105 * {@inheritDoc}
106 */
107 public String getPreview() {
108 StringBuffer buf= new StringBuffer();
109
110 buf.append("class E {\n"); //$NON-NLS-1$
111 if (isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS) && isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS_OVERRIDE)) {
112 buf.append(" @Nullable\n"); //$NON-NLS-1$
113 }
114 buf.append(" public Object foo() { return null; }\n"); //$NON-NLS-1$
115 buf.append("}\n"); //$NON-NLS-1$
116
117 return buf.toString();
118 }
119
120 /**
121 * {@inheritDoc}
122 */
123 public boolean canFix(ICompilationUnit compilationUnit, IProblemLocation problem) {
124 int id= problem.getProblemId();
125
126 if (this.master.isMissingNullableAnnotationProblem(id)) {
127 if (isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS) && isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS_NULLABLE)) {
128 if (this.master.hasExplicitNullnessAnnotation(compilationUnit, problem.getOffset()))
129 return false;
130 return true;
131 }
132 }
133
134 return false;
135 }
136
137
138 /**
139 * {@inheritDoc}
140 */
141 public int computeNumberOfFixes(CompilationUnit compilationUnit) {
142 // note that this method also counts problems that cannot be fixed by this fix
143 // because a method already has an explicit null annotation. We cannot check
144 // here (which would be a bit expensive anyway) because we have no proper
145 // problemlocation.
146 int result= 0;
147
148 boolean addAnnotations= isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS);
149 boolean addMissingNullable= addAnnotations && isEnabled(CleanUpConstants.ADD_MISSING_ANNOTATIONS_NULLABLE);
150
151 IProblem[] problems= compilationUnit.getProblems();
152 for (int i= 0; i < problems.length; i++) {
153 int id= problems[i].getID();
154 if (addMissingNullable && this.master.isMissingNullableAnnotationProblem(id))
155 if (!this.master.hasExplicitNullnessAnnotation((ICompilationUnit) compilationUnit.getJavaElement(), problems[i].getSourceStart()))
156 result++;
157 }
158 return result;
159 }
160}