~ubuntu-branches/ubuntu/quantal/netbeans/quantal

« back to all changes in this revision

Viewing changes to java/hints/src/org/netbeans/modules/java/hints/UtilityClass.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
6
 * The contents of this file are subject to the terms of either the GNU
 
7
 * General Public License Version 2 only ("GPL") or the Common
 
8
 * Development and Distribution License("CDDL") (collectively, the
 
9
 * "License"). You may not use this file except in compliance with the
 
10
 * License. You can obtain a copy of the License at
 
11
 * http://www.netbeans.org/cddl-gplv2.html
 
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 
13
 * specific language governing permissions and limitations under the
 
14
 * License.  When distributing the software, include this License Header
 
15
 * Notice in each file and include the License file at
 
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 
17
 * particular file as subject to the "Classpath" exception as provided
 
18
 * by Sun in the GPL Version 2 section of the License file that
 
19
 * accompanied this code. If applicable, add the following below the
 
20
 * License Header, with the fields enclosed by brackets [] replaced by
 
21
 * your own identifying information:
 
22
 * "Portions Copyrighted [year] [name of copyright owner]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
26
 * Portions Copyrighted 2007 Sun Microsystems, Inc.
 
27
 */
 
28
package org.netbeans.modules.java.hints;
 
29
 
 
30
import com.sun.source.tree.ClassTree;
 
31
import com.sun.source.tree.ExpressionTree;
 
32
import com.sun.source.tree.MethodTree;
 
33
import com.sun.source.tree.ModifiersTree;
 
34
import com.sun.source.tree.StatementTree;
 
35
import com.sun.source.tree.Tree;
 
36
import com.sun.source.tree.Tree.Kind;
 
37
import com.sun.source.tree.TypeParameterTree;
 
38
import com.sun.source.tree.VariableTree;
 
39
import com.sun.source.util.TreePath;
 
40
import java.io.IOException;
 
41
import java.util.Collections;
 
42
import java.util.EnumSet;
 
43
import java.util.List;
 
44
import java.util.Set;
 
45
import java.util.prefs.Preferences;
 
46
import javax.lang.model.element.Element;
 
47
import javax.lang.model.element.ElementKind;
 
48
import javax.lang.model.element.ElementVisitor;
 
49
import javax.lang.model.element.ExecutableElement;
 
50
import javax.lang.model.element.Modifier;
 
51
import javax.lang.model.element.Name;
 
52
import javax.lang.model.element.PackageElement;
 
53
import javax.lang.model.element.TypeElement;
 
54
import javax.lang.model.element.TypeParameterElement;
 
55
import javax.lang.model.element.VariableElement;
 
56
import javax.lang.model.type.TypeMirror;
 
57
import javax.swing.JComponent;
 
58
import javax.swing.text.BadLocationException;
 
59
import javax.swing.text.Document;
 
60
import org.netbeans.api.java.source.Task;
 
61
import org.netbeans.api.java.source.CompilationInfo;
 
62
import org.netbeans.api.java.source.JavaSource;
 
63
import org.netbeans.api.java.source.ModificationResult;
 
64
import org.netbeans.api.java.source.TreePathHandle;
 
65
import org.netbeans.api.java.source.WorkingCopy;
 
66
import org.netbeans.modules.java.editor.semantic.Utilities;
 
67
import org.netbeans.modules.java.hints.spi.AbstractHint;
 
68
import org.netbeans.spi.editor.hints.ChangeInfo;
 
69
import org.netbeans.spi.editor.hints.ErrorDescription;
 
70
import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
 
71
import org.netbeans.spi.editor.hints.Fix;
 
72
import org.openide.filesystems.FileObject;
 
73
import org.openide.util.Exceptions;
 
74
import org.openide.util.NbBundle;
 
75
 
 
76
/**
 
77
 *
 
78
 * @author Jaroslav tulach
 
79
 */
 
80
public class UtilityClass extends AbstractHint implements ElementVisitor<Boolean,CompilationInfo> {
 
81
    private boolean clazz;
 
82
    private transient volatile boolean stop;
 
83
    
 
84
    /** Creates a new instance of AddOverrideAnnotation */
 
85
    private UtilityClass(boolean b) {
 
86
        super( false, true, b ? AbstractHint.HintSeverity.WARNING : AbstractHint.HintSeverity.CURRENT_LINE_WARNING);
 
87
        clazz = b;
 
88
    }
 
89
    
 
90
    public Set<Kind> getTreeKinds() {
 
91
        return EnumSet.of(clazz ? Kind.CLASS : Kind.METHOD); 
 
92
    }
 
93
    
 
94
    public static UtilityClass withoutConstructor() {
 
95
        return new UtilityClass(true);
 
96
    }
 
97
    public static UtilityClass withConstructor() {
 
98
        return new UtilityClass(false);
 
99
    }
 
100
 
 
101
    public List<ErrorDescription> run(CompilationInfo compilationInfo,
 
102
                                      TreePath treePath) {
 
103
        stop = false;
 
104
        try {
 
105
            Document doc = compilationInfo.getDocument();
 
106
            
 
107
            if (doc == null) {
 
108
                return null;
 
109
            }
 
110
            
 
111
            Element e = compilationInfo.getTrees().getElement(treePath);
 
112
            if (e == null) {
 
113
                return null;
 
114
            }
 
115
            
 
116
            if (clazz) {
 
117
                if (e.getKind() == ElementKind.ENUM) {
 
118
                    return null;
 
119
                }
 
120
                if (e.getKind() == ElementKind.INTERFACE) {
 
121
                    return null;
 
122
                }
 
123
                if (e.getKind() == ElementKind.ANNOTATION_TYPE) {
 
124
                    return null;
 
125
                }
 
126
                if (e.getKind() == ElementKind.CLASS) {
 
127
                    TypeMirror supr = ((TypeElement)e).getSuperclass();
 
128
                    if (supr == null) {
 
129
                        return null;
 
130
                    }
 
131
                    Element superElem = compilationInfo.getTypes().asElement(supr);
 
132
                    if (superElem instanceof TypeElement) {
 
133
                        Name superName = compilationInfo.getElements().getBinaryName((TypeElement)superElem);
 
134
                        if (superName != null && !superName.contentEquals("java.lang.Object")) {
 
135
                            return null;
 
136
                        }
 
137
                    }
 
138
                }
 
139
 
 
140
                int cnt = 0;
 
141
                for (Element m : e.getEnclosedElements()) {
 
142
                    if (stop) {
 
143
                        return null;
 
144
                    }
 
145
                    if (m.accept(this, compilationInfo)) {
 
146
                        return null;
 
147
                    }
 
148
                    if (m.getKind() == ElementKind.METHOD || m.getKind() == ElementKind.FIELD) {
 
149
                        cnt++;
 
150
                    }
 
151
                }
 
152
                
 
153
                if (cnt == 0) {
 
154
                    return null;
 
155
                }
 
156
                
 
157
            } else {
 
158
                if (e.getKind() != ElementKind.CONSTRUCTOR) {
 
159
                    return null;
 
160
                }
 
161
                ExecutableElement x = (ExecutableElement)e;
 
162
                for (Element m : x.getEnclosingElement().getEnclosedElements()) {
 
163
                    if (stop) {
 
164
                        return null;
 
165
                    }
 
166
                    if (m.accept(this, compilationInfo)) {
 
167
                        return null;
 
168
                    }
 
169
                }
 
170
                if (x.getModifiers().contains(Modifier.PROTECTED) || x.getModifiers().contains(Modifier.PUBLIC)) {
 
171
                    // ok
 
172
                } else {
 
173
                    return null;
 
174
                }
 
175
            }
 
176
            List<Fix> fixes = Collections.<Fix>singletonList(new FixImpl(
 
177
                clazz,
 
178
                TreePathHandle.create(e, compilationInfo),
 
179
                compilationInfo.getFileObject()
 
180
                ));
 
181
 
 
182
            int[] span = Utilities.findIdentifierSpan(treePath, compilationInfo, doc);
 
183
 
 
184
            if (span[0] != (-1) && span[1] != (-1)) {
 
185
                ErrorDescription ed = ErrorDescriptionFactory.createErrorDescription(
 
186
                        getSeverity().toEditorSeverity(),
 
187
                        NbBundle.getMessage(UtilityClass.class, clazz ? "MSG_UtilityClass" : "MSG_PublicConstructor"), // NOI18N
 
188
                        fixes,
 
189
                        doc,
 
190
                        doc.createPosition(span[0]),
 
191
                        doc.createPosition(span[1])
 
192
                        );
 
193
                
 
194
                return Collections.singletonList(ed);
 
195
            }
 
196
        } catch (BadLocationException e) {
 
197
            Exceptions.printStackTrace(e);
 
198
        } catch (IOException e) {
 
199
            Exceptions.printStackTrace(e);
 
200
        }
 
201
        
 
202
        return null;
 
203
    }
 
204
 
 
205
    public String getId() {
 
206
        return getClass().getName();
 
207
    }
 
208
 
 
209
    public String getDisplayName() {
 
210
        return NbBundle.getMessage(UtilityClass.class, clazz ? "MSG_UtilityClass" : "MSG_PublicConstructor"); // NOI18N
 
211
    }
 
212
 
 
213
    public String getDescription() {
 
214
        return NbBundle.getMessage(UtilityClass.class, clazz ? "HINT_UtilityClass" : "HINT_PublicConstructor"); // NOI18N
 
215
    }
 
216
 
 
217
    public void cancel() {
 
218
        // XXX implement me 
 
219
    }
 
220
    
 
221
    public Preferences getPreferences() {
 
222
        return null;
 
223
    }
 
224
    
 
225
    @Override
 
226
    public JComponent getCustomizer(Preferences node) {
 
227
        return null;
 
228
    }    
 
229
          
 
230
    public Boolean visit(Element arg0, CompilationInfo arg1) {
 
231
        return false;
 
232
    }
 
233
 
 
234
    public Boolean visit(Element arg0) {
 
235
        return false;
 
236
    }
 
237
 
 
238
    public Boolean visitPackage(PackageElement arg0, CompilationInfo arg1) {
 
239
        return false;
 
240
    }
 
241
 
 
242
    public Boolean visitType(TypeElement arg0, CompilationInfo arg1) {
 
243
        return false;
 
244
    }
 
245
 
 
246
    public Boolean visitVariable(VariableElement v, CompilationInfo arg1) {
 
247
        return !v.getModifiers().contains(Modifier.STATIC);
 
248
    }
 
249
 
 
250
    public Boolean visitExecutable(ExecutableElement m, CompilationInfo arg1) {
 
251
        if (clazz) {
 
252
            return !m.getModifiers().contains(Modifier.STATIC) && !arg1.getElementUtilities().isSynthetic(m);
 
253
        } else {
 
254
            return !m.getModifiers().contains(Modifier.STATIC) && !m.getSimpleName().contentEquals("<init>"); // NOI18N
 
255
        }
 
256
    }
 
257
 
 
258
    public Boolean visitTypeParameter(TypeParameterElement arg0, CompilationInfo arg1) {
 
259
        return false;
 
260
    }
 
261
 
 
262
    public Boolean visitUnknown(Element arg0, CompilationInfo arg1) {
 
263
        return false;
 
264
    }
 
265
 
 
266
    private static final class FixImpl implements Fix, Task<WorkingCopy> {
 
267
        private TreePathHandle handle;
 
268
        private FileObject file;
 
269
        private boolean clazz;
 
270
        
 
271
        public FixImpl(boolean clazz, TreePathHandle handle, FileObject file) {
 
272
            this.handle = handle;
 
273
            this.file = file;
 
274
            this.clazz = clazz;
 
275
        }
 
276
        
 
277
        public String getText() {
 
278
            return NbBundle.getMessage(UtilityClass.class, clazz ? "MSG_PrivateConstructor" : "MSG_MakePrivate"); // NOI18N
 
279
        }
 
280
        
 
281
        public ChangeInfo implement() throws IOException {
 
282
            ModificationResult result = JavaSource.forFileObject(file).runModificationTask(this);
 
283
            result.commit();
 
284
            return null;
 
285
        }
 
286
        
 
287
        @Override public String toString() {
 
288
            return "FixUtilityClass"; // NOI18N
 
289
        }
 
290
 
 
291
        public void run(WorkingCopy wc) throws Exception {
 
292
            wc.toPhase(JavaSource.Phase.RESOLVED);
 
293
            
 
294
            Element e = handle.resolveElement(wc);
 
295
            if (e == null) {
 
296
                return;
 
297
            }
 
298
            Tree outer = wc.getTrees().getTree(e);
 
299
            if (clazz) {
 
300
                if (outer == null || outer.getKind() != Kind.CLASS) {
 
301
                    return;
 
302
                }
 
303
                ClassTree cls = (ClassTree)outer;
 
304
                
 
305
                ModifiersTree modifiers = wc.getTreeMaker().Modifiers(Collections.singleton(Modifier.PRIVATE));
 
306
                MethodTree m = wc.getTreeMaker().Constructor(
 
307
                    modifiers, 
 
308
                    Collections.<TypeParameterTree>emptyList(), 
 
309
                    Collections.<VariableTree>emptyList(), 
 
310
                    Collections.<ExpressionTree>emptyList(), 
 
311
                    wc.getTreeMaker().Block(Collections.<StatementTree>emptyList(), false)
 
312
                );
 
313
                wc.rewrite(cls, wc.getTreeMaker().addClassMember(cls, m));
 
314
            } else {
 
315
                if (outer == null || outer.getKind() != Kind.METHOD) {
 
316
                    return;
 
317
                }
 
318
                MethodTree met = (MethodTree)outer;
 
319
                
 
320
                ModifiersTree modifiers = wc.getTreeMaker().Modifiers(Collections.singleton(Modifier.PRIVATE), met.getModifiers().getAnnotations());
 
321
                wc.rewrite(met.getModifiers(), modifiers);
 
322
            }
 
323
        }
 
324
    }
 
325
    
 
326
}