KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > java > hints > ImplementAllAbstractMethodsCreator


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.java.hints;
20
21 import com.sun.source.tree.ClassTree;
22 import com.sun.source.tree.ModifiersTree;
23 import com.sun.source.tree.NewClassTree;
24 import com.sun.source.tree.Tree;
25 import com.sun.source.tree.Tree.Kind;
26 import com.sun.source.util.TreePath;
27 import com.sun.source.util.TreePathScanner;
28 import java.io.IOException JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.Arrays JavaDoc;
31 import java.util.HashSet JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Set JavaDoc;
34 import javax.lang.model.element.Element;
35 import javax.lang.model.element.ExecutableElement;
36 import javax.lang.model.element.Modifier;
37 import javax.lang.model.util.ElementFilter;
38 import javax.swing.text.BadLocationException JavaDoc;
39 import org.netbeans.api.java.source.CancellableTask;
40 import org.netbeans.api.java.source.CompilationInfo;
41 import org.netbeans.api.java.source.JavaSource;
42 import org.netbeans.api.java.source.JavaSource.Phase;
43 import org.netbeans.api.java.source.WorkingCopy;
44 import org.netbeans.modules.java.editor.codegen.GeneratorUtils;
45 import org.netbeans.modules.java.hints.spi.ErrorRule;
46 import org.netbeans.spi.editor.hints.ChangeInfo;
47 import org.netbeans.spi.editor.hints.Fix;
48 import org.openide.util.Exceptions;
49
50 /**
51  *
52  * @author Jan Lahoda
53  */

54 public final class ImplementAllAbstractMethodsCreator implements ErrorRule<Void JavaDoc> {
55     
56     /** Creates a new instance of ImplementAllAbstractMethodsCreator */
57     public ImplementAllAbstractMethodsCreator() {
58     }
59
60     public Set JavaDoc<String JavaDoc> getCodes() {
61         return new HashSet JavaDoc<String JavaDoc>(Arrays.asList(
62                 "compiler.err.abstract.cant.be.instantiated",
63                 "compiler.err.does.not.override.abstract",
64                 "compiler.err.abstract.cant.be.instantiated"));
65     }
66     
67     public List JavaDoc<Fix> run(final CompilationInfo info, String JavaDoc diagnosticKey, final int offset, TreePath treePath, Data<Void JavaDoc> data) {
68         final List JavaDoc<Fix> result = new ArrayList JavaDoc<Fix>();
69
70         analyze(info.getJavaSource(), offset, info, new Performer() {
71             public void fixAllAbstractMethods(TreePath pathToModify, Tree toModify) {
72                 result.add(new FixImpl(info.getJavaSource(), offset, null));
73             }
74             public void makeClassAbstract(Tree toModify, String JavaDoc className) {
75                 result.add(new FixImpl(info.getJavaSource(), offset, className));
76             }
77         });
78         
79         return result;
80     }
81     
82     public void cancel() {
83         //XXX: not done yet
84
}
85
86     public String JavaDoc getId() {
87         return ImplementAllAbstractMethodsCreator.class.getName();
88     }
89     
90     public String JavaDoc getDisplayName() {
91         return "Implement All Abstract Methods Fix";
92     }
93     
94     public String JavaDoc getDescription() {
95         return "Implement All Abstract Methods Fix";
96     }
97     
98     private static interface Performer {
99
100         public void fixAllAbstractMethods(TreePath pathToModify, Tree toModify);
101         public void makeClassAbstract(Tree toModify, String JavaDoc className);
102
103     }
104
105     private static void analyze(JavaSource js, int offset, CompilationInfo info, Performer performer) {
106         final TreePath path = info.getTreeUtilities().pathFor(offset + 1);
107         Element e = info.getTrees().getElement(path);
108         boolean isUsableElement = e != null && (e.getKind().isClass() || e.getKind().isInterface());
109         
110         if (isUsableElement) {
111             //#85806: do not propose implement all abstract methods when the current class contains abstract methods:
112
for (ExecutableElement ee : ElementFilter.methodsIn(e.getEnclosedElements())) {
113                 if (ee.getModifiers().contains(Modifier.ABSTRACT)) {
114                     performer.makeClassAbstract(path.getLeaf(), e.getSimpleName().toString());
115                     return;
116                 }
117             }
118             
119             performer.fixAllAbstractMethods(path, path.getLeaf());
120         } else {
121             if (path.getLeaf().getKind() == Kind.NEW_CLASS) {
122                 //if the parent of path.getLeaf is an error, the situation probably is like:
123
//new Runnable {}
124
//(missing '()' for constructor)
125
//do not propose the hint in this case:
126
final boolean[] parentError = new boolean[] {false};
127                 new TreePathScanner() {
128                     @Override JavaDoc
129                     public Object JavaDoc visitNewClass(NewClassTree nct, Object JavaDoc o) {
130                         if (path.getLeaf() == nct) {
131                             parentError[0] = getCurrentPath().getParentPath().getLeaf().getKind() == Kind.ERRONEOUS;
132                         }
133                         return super.visitNewClass(nct, o);
134                     }
135                 }.scan(path.getParentPath(), null);
136                 if (!parentError[0]) {
137                     performer.fixAllAbstractMethods(path, path.getLeaf());
138                 }
139             }
140         }
141     }
142
143     private static final class FixImpl implements Fix {
144
145         private JavaSource js;
146         private int offset;
147         private String JavaDoc makeClassAbstractName;
148         
149         public FixImpl(JavaSource js, int offset, String JavaDoc makeClassAbstractName) {
150             this.js = js;
151             this.offset = offset;
152             this.makeClassAbstractName = makeClassAbstractName;
153         }
154         
155         public String JavaDoc getText() {
156             return makeClassAbstractName == null ? "Implement all abstract methods" : "Make class " + makeClassAbstractName + " abstract";
157         }
158
159         public ChangeInfo implement() {
160             try {
161                 final boolean[] repeat = new boolean[] {true};
162                 
163                 while (repeat[0]) {
164                     repeat[0] = false;
165                     js.runModificationTask(new CancellableTask<WorkingCopy>() {
166                         public void cancel() {
167                         }
168                         public void run(final WorkingCopy copy) throws IOException JavaDoc {
169                             copy.toPhase(Phase.RESOLVED);
170                             analyze(js, offset, copy, new Performer() {
171                                 public void fixAllAbstractMethods(TreePath pathToModify, Tree toModify) {
172                                     if (toModify.getKind() == Kind.NEW_CLASS) {
173                                         int insertOffset = (int) copy.getTrees().getSourcePositions().getEndPosition(copy.getCompilationUnit(), toModify);
174                                         if (insertOffset != (-1)) {
175                                             try {
176                                                 copy.getDocument().insertString(insertOffset, " {}", null);
177                                                 offset = insertOffset + 1;
178                                                 repeat[0] = true;
179                                             } catch (BadLocationException JavaDoc e) {
180                                                 Exceptions.printStackTrace(e);
181                                             } catch (IOException JavaDoc e) {
182                                                 Exceptions.printStackTrace(e);
183                                             }
184                                         }
185                                     } else {
186                                         GeneratorUtils.generateAllAbstractMethodImplementations(copy, pathToModify);
187                                     }
188                                 }
189                                 public void makeClassAbstract(Tree toModify, String JavaDoc className) {
190                                     //the toModify has to be a class tree:
191
if (toModify.getKind() == Kind.CLASS) {
192                                         ClassTree clazz = (ClassTree) toModify;
193                                         ModifiersTree modifiers = clazz.getModifiers();
194                                         Set JavaDoc<Modifier> newModifiersSet = new HashSet JavaDoc<Modifier>(modifiers.getFlags());
195                                         
196                                         newModifiersSet.add(Modifier.ABSTRACT);
197                                         
198                                         copy.rewrite(modifiers, copy.getTreeMaker().Modifiers(newModifiersSet, modifiers.getAnnotations()));
199                                     }
200                                 }
201                             });
202                         }
203                     }).commit();
204                 }
205             } catch (IOException JavaDoc e) {
206                 Exceptions.printStackTrace(e);
207             }
208             return null;
209         }
210         
211     }
212 }
213
Popular Tags