This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 89258
Collapse All | Expand All

(-)a/java.hints/src/org/netbeans/modules/java/hints/Bundle.properties (-1 / +6 lines)
Lines 76-82 Link Here
76
LBL_Imports_EXCLUDED=Import from Excluded
76
LBL_Imports_EXCLUDED=Import from Excluded
77
LBL_Imports_STAR=Star import
77
LBL_Imports_STAR=Star import
78
78
79
DSC_Imports_DELAGATE=Delegate - non GUI
79
DSC_Imports_DELEGATE=Delegate - non GUI
80
DSC_Imports_UNUSED=Unused Import
80
DSC_Imports_UNUSED=Unused Import
81
DSC_Imports_DUPLICATE=Multiple Import
81
DSC_Imports_DUPLICATE=Multiple Import
82
DSC_Imports_SAME_PACKAGE=Import From The Same Package
82
DSC_Imports_SAME_PACKAGE=Import From The Same Package
Lines 262-267 Link Here
262
ERR_SynchronizationOnNonFinalField=Synchronization on non-final field
262
ERR_SynchronizationOnNonFinalField=Synchronization on non-final field
263
DN_SynchronizationOnNonFinalField=Synchronization on non-final field
263
DN_SynchronizationOnNonFinalField=Synchronization on non-final field
264
264
265
HINT_StaticImport=Convert method to static import
266
DSC_StaticImport=Convert method to static import
267
ERR_StaticImport=Convert method to static import
268
DN_StaticImport=Convert method to static import
269
265
HINT_SuspiciousCall=Suspicious call to {0}:\nExpected type {2}, actual type {1}
270
HINT_SuspiciousCall=Suspicious call to {0}:\nExpected type {2}, actual type {1}
266
HINT_SuspiciousCallIncompatibleTypes=Suspicious call to {0}:\nGiven object cannot contain instances of {1} (expected {2})
271
HINT_SuspiciousCallIncompatibleTypes=Suspicious call to {0}:\nGiven object cannot contain instances of {1} (expected {2})
267
DN_CollectionRemove=Suspicous method call
272
DN_CollectionRemove=Suspicous method call
(-)7962d72beb03 (+194 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 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 2009 Sun Microsystems, Inc.
27
 */
28
package org.netbeans.modules.java.hints;
29
30
import com.sun.source.tree.CompilationUnitTree;
31
import com.sun.source.tree.ExpressionTree;
32
import com.sun.source.tree.ImportTree;
33
import com.sun.source.tree.MethodInvocationTree;
34
import com.sun.source.tree.Tree.Kind;
35
import com.sun.source.util.TreePath;
36
import java.util.ArrayList;
37
import java.util.Collections;
38
import java.util.EnumSet;
39
import java.util.List;
40
import java.util.Set;
41
import java.util.concurrent.atomic.AtomicBoolean;
42
import javax.lang.model.element.Element;
43
import javax.lang.model.element.Modifier;
44
import org.netbeans.api.java.source.CompilationInfo;
45
import org.netbeans.api.java.source.JavaSource;
46
import org.netbeans.api.java.source.JavaSource.Phase;
47
import org.netbeans.api.java.source.Task;
48
import org.netbeans.api.java.source.TreeMaker;
49
import org.netbeans.api.java.source.TreePathHandle;
50
import org.netbeans.api.java.source.WorkingCopy;
51
import org.netbeans.modules.java.hints.spi.AbstractHint;
52
import org.netbeans.spi.editor.hints.ChangeInfo;
53
import org.netbeans.spi.editor.hints.ErrorDescription;
54
import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
55
import org.netbeans.spi.editor.hints.Fix;
56
import org.openide.util.NbBundle;
57
import static org.netbeans.modules.editor.java.Utilities.getElementName;
58
59
/**
60
 * Hint offering to convert a qualified static method into a static import. e.g.
61
 * <code>Math.abs(-1)</code> -> <code>abs(-1)</code>.
62
 *
63
 * @author Samuel Halliday
64
 * @see <a href="http://www.netbeans.org/issues/show_bug.cgi?id=89258">RFE 89258</a>
65
 */
66
public class StaticImport extends AbstractHint {
67
68
    private final AtomicBoolean cancel = new AtomicBoolean();
69
70
    public StaticImport() {
71
        super(true, false, HintSeverity.CURRENT_LINE_WARNING);
72
    }
73
74
    @Override
75
    public String getDescription() {
76
        return NbBundle.getMessage(StaticImport.class, "DSC_StaticImport");
77
    }
78
79
    public Set<Kind> getTreeKinds() {
80
        return EnumSet.of(Kind.METHOD_INVOCATION);
81
    }
82
83
    public List<ErrorDescription> run(CompilationInfo info, TreePath treePath) {
84
        if (treePath.getLeaf().getKind() != Kind.METHOD_INVOCATION) {
85
            return null; // XXX is this sanity check needed?
86
        }
87
        MethodInvocationTree tree = (MethodInvocationTree) treePath.getLeaf();
88
        ExpressionTree identifier = tree.getMethodSelect();
89
        Element e = info.getTrees().getElement(new TreePath(treePath, identifier));
90
        if (e == null || !e.getModifiers().contains(Modifier.STATIC)) {
91
            return null;
92
        }
93
94
        int start = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), identifier);
95
        int end = (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), identifier);
96
97
        // XXX is there a better way to work out if the method is qualified
98
        if (!identifier.toString().contains(".")) { // NOI18N
99
            return null;
100
        }
101
102
        // TODO ignore case where containing class not imported yet (that's for errors to handle)
103
104
        // TODO ignore case where source code is less than Java 1.5
105
106
        List<Fix> fixes = Collections.<Fix>singletonList(new FixImpl(TreePathHandle.create(treePath, info)));
107
108
        String desc = NbBundle.getMessage(AddOverrideAnnotation.class, "HINT_StaticImport");
109
        ErrorDescription ed = ErrorDescriptionFactory.createErrorDescription(getSeverity().toEditorSeverity(), desc, fixes, info.getFileObject(), start, end);
110
        if (cancel.get()) {
111
            return null;
112
        }
113
        return Collections.singletonList(ed);
114
    }
115
116
    public String getId() {
117
        return StaticImport.class.getName();
118
    }
119
120
    public String getDisplayName() {
121
        return NbBundle.getMessage(StaticImport.class, "DSC_StaticImport");
122
    }
123
124
    public void cancel() {
125
        cancel.set(true);
126
    }
127
128
    private static final class FixImpl implements Fix, Task<WorkingCopy> {
129
130
        private final TreePathHandle handle;
131
132
        private FixImpl(TreePathHandle handle) {
133
            this.handle = handle;
134
        }
135
136
        public String getText() {
137
            return NbBundle.getMessage(StaticImport.class, "HINT_StaticImport");
138
        }
139
140
        public ChangeInfo implement() throws Exception {
141
            JavaSource js = JavaSource.forFileObject(handle.getFileObject());
142
            js.runModificationTask(this).commit();
143
            return null;
144
        }
145
146
        public void run(WorkingCopy copy) throws Exception {
147
            if (copy.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) {
148
                return;
149
            }
150
            TreePath path = handle.resolve(copy);
151
            if (path == null || path.getLeaf().getKind() != Kind.METHOD_INVOCATION) {
152
                return; // XXX is this sanity check needed?
153
            }
154
            Element el = copy.getTrees().getElement(path);
155
            CharSequence fqn = getElementName(el.getEnclosingElement(), true) + "." + el.getSimpleName();
156
            TreeMaker make = copy.getTreeMaker();
157
158
            MethodInvocationTree tree = (MethodInvocationTree) path.getLeaf();
159
            copy.rewrite(tree.getMethodSelect(), make.Identifier(el));
160
161
            CompilationUnitTree cut = copy.getCompilationUnit();
162
            TreePath klassPath = getContainingClass(path);
163
            Element klassEl = copy.getTrees().getElement(klassPath);
164
            if (el.getEnclosingElement().equals(klassEl)) {
165
                return;
166
            }
167
168
            // XXX can't use JavaFixAllImports.addImports because no support for static imports
169
            List<ImportTree> imports = new ArrayList<ImportTree>(cut.getImports());
170
            ImportTree imp = make.Import(make.Identifier(fqn), true);
171
            String impS = imp.getQualifiedIdentifier().toString();
172
            for (ImportTree i : imports) {
173
                if (!i.isStatic()) {
174
                    continue;
175
                }
176
                String iS = i.getQualifiedIdentifier().toString();
177
                // XXX dependence on undocumented form of toString
178
                if (impS.equals(iS) || (iS.endsWith(".*") && impS.startsWith(iS.substring(0, iS.length() - 2)))) { // NOI18N
179
                    return;
180
                }
181
            }
182
            imports.add(imp); // XXX smart insertion
183
            CompilationUnitTree nue = make.CompilationUnit(cut.getPackageName(), imports, cut.getTypeDecls(), cut.getSourceFile());
184
            copy.rewrite(cut, nue);
185
        }
186
187
        private TreePath getContainingClass(TreePath tp) {
188
            while (tp != null && tp.getLeaf().getKind() != Kind.CLASS) {
189
                tp = tp.getParentPath();
190
            }
191
            return tp;
192
        }
193
    }
194
}
(-)a/java.hints/src/org/netbeans/modules/java/hints/resources/layer.xml (+1 lines)
Lines 137-142 Link Here
137
                        <attr name="instanceCreate" methodvalue="org.netbeans.modules.java.hints.EqualsHint.getDelegate"/>
137
                        <attr name="instanceCreate" methodvalue="org.netbeans.modules.java.hints.EqualsHint.getDelegate"/>
138
                    </file>
138
                    </file>
139
                    <file name="org-netbeans-modules-java-hints-EqualsMethodHint.instance"/>
139
                    <file name="org-netbeans-modules-java-hints-EqualsMethodHint.instance"/>
140
                    <file name="org-netbeans-modules-java-hints-StaticImport.instance"/>
140
                    <file name="org-netbeans-modules-java-hints-SyncOnNonFinal.instance"/>
141
                    <file name="org-netbeans-modules-java-hints-SyncOnNonFinal.instance"/>
141
                    <file name="org-netbeans-modules-java-hints-CollectionRemove.instance"/>
142
                    <file name="org-netbeans-modules-java-hints-CollectionRemove.instance"/>
142
                </folder>
143
                </folder>

Return to bug 89258