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 / +7 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 263-268 Link Here
263
ERR_SynchronizationOnNonFinalField=Synchronization on non-final field
263
ERR_SynchronizationOnNonFinalField=Synchronization on non-final field
264
DN_SynchronizationOnNonFinalField=Synchronization on non-final field
264
DN_SynchronizationOnNonFinalField=Synchronization on non-final field
265
265
266
HINT_StaticImport=Convert method to static import
267
HINT_StaticImport2=Add static import for {0}
268
DSC_StaticImport=Convert method to static import
269
ERR_StaticImport=Convert method to static import
270
DN_StaticImport=Convert method to static import
271
266
HINT_SuspiciousCall=Suspicious call to {0}:\nExpected type {2}, actual type {1}
272
HINT_SuspiciousCall=Suspicious call to {0}:\nExpected type {2}, actual type {1}
267
HINT_SuspiciousCallIncompatibleTypes=Suspicious call to {0}:\nGiven object cannot contain instances of {1} (expected {2})
273
HINT_SuspiciousCallIncompatibleTypes=Suspicious call to {0}:\nGiven object cannot contain instances of {1} (expected {2})
268
DN_CollectionRemove=Suspicous method call
274
DN_CollectionRemove=Suspicous method call
(-)3662dc3ca4aa (+346 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.Collections;
37
import java.util.EnumSet;
38
import java.util.List;
39
import java.util.Set;
40
import java.util.concurrent.atomic.AtomicBoolean;
41
import javax.lang.model.element.Element;
42
import javax.lang.model.element.ElementKind;
43
import javax.lang.model.element.Modifier;
44
import javax.lang.model.element.TypeElement;
45
import javax.lang.model.type.TypeMirror;
46
import javax.lang.model.util.Types;
47
import org.netbeans.api.java.source.CompilationInfo;
48
import org.netbeans.api.java.source.ElementUtilities;
49
import org.netbeans.api.java.source.JavaSource;
50
import org.netbeans.api.java.source.JavaSource.Phase;
51
import org.netbeans.api.java.source.SourceUtils;
52
import org.netbeans.api.java.source.Task;
53
import org.netbeans.api.java.source.TreeMaker;
54
import org.netbeans.api.java.source.TreePathHandle;
55
import org.netbeans.api.java.source.WorkingCopy;
56
import org.netbeans.modules.java.hints.spi.AbstractHint;
57
import org.netbeans.spi.editor.hints.ChangeInfo;
58
import org.netbeans.spi.editor.hints.ErrorDescription;
59
import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
60
import org.netbeans.spi.editor.hints.Fix;
61
import org.openide.util.NbBundle;
62
import static org.netbeans.modules.editor.java.Utilities.getElementName;
63
64
/**
65
 * Hint offering to convert a qualified static method into a static import. e.g.
66
 * <code>Math.abs(-1)</code> -> <code>abs(-1)</code>.
67
 *
68
 * @author Sam Halliday
69
 * @see <a href="http://www.netbeans.org/issues/show_bug.cgi?id=89258">RFE 89258</a>
70
 */
71
public class StaticImport extends AbstractHint {
72
73
    private final AtomicBoolean cancel = new AtomicBoolean();
74
75
    public StaticImport() {
76
        super(true, false, HintSeverity.CURRENT_LINE_WARNING);
77
    }
78
79
    @Override
80
    public String getDescription() {
81
        return NbBundle.getMessage(StaticImport.class, "DSC_StaticImport");
82
    }
83
84
    public Set<Kind> getTreeKinds() {
85
        return EnumSet.of(Kind.METHOD_INVOCATION);
86
    }
87
88
    public List<ErrorDescription> run(CompilationInfo info, TreePath treePath) {
89
        if (treePath.getLeaf().getKind() != Kind.METHOD_INVOCATION) {
90
            return null;
91
        }
92
        cancel.set(false);
93
        MethodInvocationTree tree = (MethodInvocationTree) treePath.getLeaf();
94
        ExpressionTree identifier = tree.getMethodSelect();
95
        if (identifier.getKind() != Kind.MEMBER_SELECT) {
96
            return null;
97
        }
98
        Element e = info.getTrees().getElement(new TreePath(treePath, identifier));
99
        if (e == null || !e.getModifiers().contains(Modifier.STATIC)) {
100
            return null;
101
        }
102
        Element enclosingEl = e.getEnclosingElement();
103
        if (enclosingEl == null) {
104
            return null;
105
        }
106
        // XXX is there a better way to ignore error cases
107
        String sn = e.getSimpleName().toString();
108
        if (!isValidStaticMethod(info, getElementName(enclosingEl, true).toString(), sn)) {
109
            return null;
110
        }
111
        // TODO ignore case where source code is less than Java 1.5
112
        Element klass = info.getTrees().getElement(getContainingClass(treePath));
113
        String fqn = null;
114
        String fqn1 = getMethodFqn(e);
115
        if (!isSubTypeOrInnerOfSubType(info, klass, enclosingEl) && !isStaticallyImported(info, fqn1)) {
116
            if (hasMethodNameClash(info, klass, sn) || hasStaticImportSimpleNameClash(info, sn)) {
117
                return null;
118
            }
119
            fqn = fqn1;
120
        }
121
        List<Fix> fixes = Collections.<Fix>singletonList(new FixImpl(TreePathHandle.create(treePath, info), fqn));
122
        String desc = NbBundle.getMessage(AddOverrideAnnotation.class, "HINT_StaticImport");
123
        int start = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), identifier);
124
        int end = (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), identifier);
125
        ErrorDescription ed = ErrorDescriptionFactory.createErrorDescription(getSeverity().toEditorSeverity(), desc, fixes, info.getFileObject(), start, end);
126
        if (cancel.get()) {
127
            return null;
128
        }
129
        return Collections.singletonList(ed);
130
    }
131
132
    public String getId() {
133
        return StaticImport.class.getName();
134
    }
135
136
    public String getDisplayName() {
137
        return NbBundle.getMessage(StaticImport.class, "DSC_StaticImport");
138
    }
139
140
    public void cancel() {
141
        cancel.set(true);
142
    }
143
144
    public static final class FixImpl implements Fix, Task<WorkingCopy> {
145
146
        private final TreePathHandle handle;
147
        private final String fqn;
148
149
        /**
150
         * @param handle to the METHOD_INVOCATION
151
         * @param fqn to static import, or null to not perform any imports
152
         */
153
        public FixImpl(TreePathHandle handle, String fqn) {
154
            this.handle = handle;
155
            this.fqn = fqn;
156
        }
157
158
        public String getText() {
159
            if (fqn == null) {
160
                return NbBundle.getMessage(StaticImport.class, "HINT_StaticImport");
161
            } else {
162
                return NbBundle.getMessage(StaticImport.class, "HINT_StaticImport2", fqn);
163
            }
164
        }
165
166
        public ChangeInfo implement() throws Exception {
167
            JavaSource js = JavaSource.forFileObject(handle.getFileObject());
168
            js.runModificationTask(this).commit();
169
            return null;
170
        }
171
172
        public void run(WorkingCopy copy) throws Exception {
173
            if (copy.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) {
174
                return;
175
            }
176
            TreePath treePath = handle.resolve(copy);
177
            if (treePath == null || treePath.getLeaf().getKind() != Kind.METHOD_INVOCATION) {
178
                return;
179
            }
180
            MethodInvocationTree tree = (MethodInvocationTree) treePath.getLeaf();
181
            ExpressionTree identifier = tree.getMethodSelect();
182
            Element e = copy.getTrees().getElement(new TreePath(treePath, identifier));
183
            if (e == null || !e.getModifiers().contains(Modifier.STATIC) || identifier.getKind() != Kind.MEMBER_SELECT) {
184
                return;
185
            }
186
            TreeMaker make = copy.getTreeMaker();
187
            copy.rewrite(identifier, make.Identifier(e.getSimpleName()));
188
            if (fqn == null) {
189
                return;
190
            }
191
            CompilationUnitTree cut = copy.getCompilationUnit();
192
            CompilationUnitTree nue = SourceUtils.addStaticImports(cut, Collections.singletonList(fqn), make);
193
            copy.rewrite(cut, nue);
194
        }
195
    }
196
197
    // returns true if a METHOD is enclosed in element with simple name sn
198
    private static boolean hasMethodWithSimpleName(CompilationInfo info, Element element, final String sn) {
199
        Iterable<? extends Element> members =
200
                info.getElementUtilities().getMembers(element.asType(), new ElementUtilities.ElementAcceptor() {
201
202
            public boolean accept(Element e, TypeMirror type) {
203
                if (e.getKind() == ElementKind.METHOD && e.getSimpleName().toString().equals(sn)) {
204
                    return true;
205
                }
206
                return false;
207
            }
208
        });
209
        return members.iterator().hasNext();
210
    }
211
212
    /**
213
     * @param info
214
     * @param simpleName of static method.
215
     * @return true if a static import exists with the same simple name.
216
     * Caveat, expect false positives on protected and default visibility methods from wildcard static imports.
217
     */
218
    public static boolean hasStaticImportSimpleNameClash(CompilationInfo info, String simpleName) {
219
        for (ImportTree i : info.getCompilationUnit().getImports()) {
220
            if (!i.isStatic()) {
221
                continue;
222
            }
223
            String q = i.getQualifiedIdentifier().toString();
224
            if (q.endsWith(".*")) { //NOI18N
225
                TypeElement ie = info.getElements().getTypeElement(q.substring(0, q.length() - 2));
226
                if (ie == null) {
227
                    continue;
228
                }
229
                for (Element enclosed : ie.getEnclosedElements()) {
230
                    Set<Modifier> modifiers = enclosed.getModifiers();
231
                    if (enclosed.getKind() != ElementKind.METHOD || !modifiers.contains(Modifier.STATIC) || modifiers.contains(Modifier.PRIVATE)) {
232
                        continue;
233
                    }
234
                    String sn1 = enclosed.getSimpleName().toString();
235
                    if (simpleName.equals(sn1)) {
236
                        return true;
237
                    }
238
                }
239
            } else {
240
                int endIndex = q.lastIndexOf("."); //NOI18N
241
                if (endIndex == -1 || endIndex >= q.length() - 1) {
242
                    continue;
243
                }
244
                if (q.substring(endIndex).equals(simpleName)) {
245
                    return true;
246
                }
247
            }
248
        }
249
        return false;
250
    }
251
252
    /**
253
     * @param info
254
     * @param t1
255
     * @param t3
256
     * @return true iff the first type (or its containing class in the case of inner classes)
257
     * is a subtype of the second.
258
     * @see Types#isSubtype(javax.lang.model.type.TypeMirror, javax.lang.model.type.TypeMirror)
259
     */
260
    private static boolean isSubTypeOrInnerOfSubType(CompilationInfo info, Element t1, Element t2) {
261
        boolean isSubtype = info.getTypes().isSubtype(t1.asType(), t2.asType());
262
        boolean isInnerClass = t1.getEnclosingElement().getKind() == ElementKind.CLASS;
263
        return isSubtype || (isInnerClass && info.getTypes().isSubtype(t1.getEnclosingElement().asType(), t2.asType()));
264
    }
265
266
    /**
267
     * @param info
268
     * @param klass the element for a CLASS
269
     * @param member the STATIC, MEMBER_SELECT Element for a MethodInvocationTree
270
     * @return true if member has a simple name which would clash with local or inherited
271
     * methods in klass (which may be an inner or static class).
272
     */
273
    public static boolean hasMethodNameClash(CompilationInfo info, Element klass, String simpleName) {
274
        assert klass != null;
275
        assert klass.getKind() == ElementKind.CLASS;
276
277
        // check the members and inherited members of the klass
278
        if (hasMethodWithSimpleName(info, klass, simpleName)) {
279
            return true;
280
        }
281
        Element klassEnclosing = klass.getEnclosingElement();
282
        return (klassEnclosing != null && klassEnclosing.getKind() == ElementKind.CLASS && hasMethodWithSimpleName(info, klassEnclosing, simpleName));
283
    }
284
285
    /**
286
     * @param e
287
     * @return the FQN for a METHOD Element
288
     */
289
    public static String getMethodFqn(Element e) {
290
        // TODO: or alternatively, upgrade getElementName to handled METHOD
291
        assert e.getKind() == ElementKind.METHOD;
292
        return getElementName(e.getEnclosingElement(), true) + "." + e.getSimpleName();
293
    }
294
295
    /**
296
     * @param tp
297
     * @return the first path which is a CLASS or null if none found
298
     */
299
    public static TreePath getContainingClass(TreePath tp) {
300
        while (tp != null && tp.getLeaf().getKind() != Kind.CLASS) {
301
            tp = tp.getParentPath();
302
        }
303
        return tp;
304
    }
305
306
    // return true if the fqn already has a static import
307
    private static boolean isStaticallyImported(CompilationInfo info, String fqn) {
308
        for (ImportTree i : info.getCompilationUnit().getImports()) {
309
            if (!i.isStatic()) {
310
                continue;
311
            }
312
            String q = i.getQualifiedIdentifier().toString();
313
            if (q.endsWith(".*") && fqn.startsWith(q.substring(0, q.length() - 1))) { //NOI18N
314
                return true;
315
            }
316
            if (q.equals(fqn)) {
317
                return true;
318
            }
319
        }
320
        return false;
321
    }
322
323
    /**
324
     * @param info
325
     * @param fqn of the containing class
326
     * @param simpleName of the method
327
     * @return true if {@code fqn.simpleName} represents a valid static method
328
     */
329
    public static boolean isValidStaticMethod(CompilationInfo info, String fqn, String simpleName) {
330
        TypeElement ie = info.getElements().getTypeElement(fqn);
331
        if (ie == null) {
332
            return false;
333
        }
334
        for (Element enclosed : ie.getEnclosedElements()) {
335
            Set<Modifier> modifiers = enclosed.getModifiers();
336
            if (enclosed.getKind() != ElementKind.METHOD || !modifiers.contains(Modifier.STATIC) || modifiers.contains(Modifier.PRIVATE)) {
337
                continue;
338
            }
339
            String sn1 = enclosed.getSimpleName().toString();
340
            if (simpleName.equals(sn1)) {
341
                return true;
342
            }
343
        }
344
        return false;
345
    }
346
}
(-)a/java.hints/src/org/netbeans/modules/java/hints/errors/ImportClass.java (-2 / +40 lines)
Lines 43-48 Link Here
43
43
44
import com.sun.source.tree.CompilationUnitTree;
44
import com.sun.source.tree.CompilationUnitTree;
45
import com.sun.source.tree.ImportTree;
45
import com.sun.source.tree.ImportTree;
46
import com.sun.source.tree.MemberSelectTree;
46
import com.sun.source.tree.MethodInvocationTree;
47
import com.sun.source.tree.MethodInvocationTree;
47
import com.sun.source.tree.Tree.Kind;
48
import com.sun.source.tree.Tree.Kind;
48
import com.sun.source.util.TreePath;
49
import com.sun.source.util.TreePath;
Lines 57-72 Link Here
57
import java.util.Set;
58
import java.util.Set;
58
import java.util.logging.Level;
59
import java.util.logging.Level;
59
import java.util.logging.Logger;
60
import java.util.logging.Logger;
61
import javax.lang.model.element.Element;
60
import javax.lang.model.element.TypeElement;
62
import javax.lang.model.element.TypeElement;
61
import org.netbeans.api.java.source.Task;
63
import org.netbeans.api.java.source.Task;
62
import org.netbeans.api.java.source.CompilationInfo;
64
import org.netbeans.api.java.source.CompilationInfo;
63
import org.netbeans.api.java.source.JavaSource;
65
import org.netbeans.api.java.source.JavaSource;
64
import org.netbeans.api.java.source.JavaSource.Phase;
66
import org.netbeans.api.java.source.JavaSource.Phase;
67
import org.netbeans.api.java.source.SourceUtils;
68
import org.netbeans.api.java.source.TreePathHandle;
65
import org.netbeans.api.java.source.WorkingCopy;
69
import org.netbeans.api.java.source.WorkingCopy;
66
import org.netbeans.api.lexer.Token;
70
import org.netbeans.api.lexer.Token;
67
import org.netbeans.modules.editor.java.Utilities;
71
import org.netbeans.modules.editor.java.Utilities;
68
import org.netbeans.modules.java.editor.imports.ComputeImports;
72
import org.netbeans.modules.java.editor.imports.ComputeImports;
69
import org.netbeans.modules.java.editor.imports.JavaFixAllImports;
73
import org.netbeans.modules.java.hints.StaticImport;
70
import org.netbeans.modules.java.hints.errors.ImportClass.ImportCandidatesHolder;
74
import org.netbeans.modules.java.hints.errors.ImportClass.ImportCandidatesHolder;
71
import org.netbeans.modules.java.hints.infrastructure.CreatorBasedLazyFixList;
75
import org.netbeans.modules.java.hints.infrastructure.CreatorBasedLazyFixList;
72
import org.netbeans.modules.java.hints.infrastructure.ErrorHintsProvider;
76
import org.netbeans.modules.java.hints.infrastructure.ErrorHintsProvider;
Lines 164-169 Link Here
164
        List<String> unfiltered = candidates.getB();
168
        List<String> unfiltered = candidates.getB();
165
        List<Fix> fixes = new ArrayList<Fix>();
169
        List<Fix> fixes = new ArrayList<Fix>();
166
        
170
        
171
        String staticSimpleName = null;
172
        TreePath mitPath = null;
173
        if (path.getLeaf().getKind() == Kind.IDENTIFIER) {
174
            TreePath parent = path.getParentPath();
175
            if (parent != null && parent.getLeaf().getKind() == Kind.MEMBER_SELECT) {
176
                mitPath = parent.getParentPath();
177
                if (mitPath != null && mitPath.getLeaf().getKind() == Kind.METHOD_INVOCATION) {
178
                    TreePath klass = StaticImport.getContainingClass(path);
179
                    Element klassElement = info.getTrees().getElement(klass);
180
                    // XXX why can't we use MemberSelectTree.getIdentifier
181
                    if (parent.getLeaf() instanceof MemberSelectTree) {
182
                        System.out.println("parent is MemberSelectTree");
183
                    } else {
184
                        System.out.println("parent is NOT a MemberSelectTree");
185
                    }
186
                    String ms = parent.getLeaf().toString();
187
                    int i = ms.lastIndexOf("."); // NOI18N
188
                    if (i != -1 && i < ms.length() - 2) {
189
                        String sn = ms.substring(i + 1);
190
                        if (!StaticImport.hasMethodNameClash(info, klassElement, sn) && !StaticImport.hasStaticImportSimpleNameClash(info, sn)) {
191
                            staticSimpleName = sn;
192
                        }
193
                    }
194
                }
195
            }
196
        }
197
167
        if (unfiltered != null && filtered != null) {
198
        if (unfiltered != null && filtered != null) {
168
            for (String fqn : unfiltered) {
199
            for (String fqn : unfiltered) {
169
                StringBuilder sort = new StringBuilder();
200
                StringBuilder sort = new StringBuilder();
Lines 186-191 Link Here
186
                sort.append(fqn);
217
                sort.append(fqn);
187
                
218
                
188
                fixes.add(new FixImport(file, fqn, sort.toString(), prefered));
219
                fixes.add(new FixImport(file, fqn, sort.toString(), prefered));
220
221
                if (staticSimpleName != null) {
222
                    String mFqn = fqn + "." + staticSimpleName; //NOI18N
223
                    if (StaticImport.isValidStaticMethod(info, fqn, staticSimpleName)) {
224
                        fixes.add(new StaticImport.FixImpl(TreePathHandle.create(mitPath, info), mFqn));
225
                    }
226
                }
189
            }
227
            }
190
        }
228
        }
191
        
229
        
Lines 340-346 Link Here
340
                            return ;
378
                            return ;
341
                        }
379
                        }
342
                        
380
                        
343
                        CompilationUnitTree cut = JavaFixAllImports.addImports(
381
                        CompilationUnitTree cut = SourceUtils.addImports(
344
                            copy.getCompilationUnit(),
382
                            copy.getCompilationUnit(),
345
                            Collections.singletonList(te.getQualifiedName().toString()),
383
                            Collections.singletonList(te.getQualifiedName().toString()),
346
                            copy.getTreeMaker()
384
                            copy.getTreeMaker()
(-)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
                    <file name="org-netbeans-modules-java-hints-FieldForUnusedParam.instance"/>
143
                    <file name="org-netbeans-modules-java-hints-FieldForUnusedParam.instance"/>
(-)a/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHint4-hints.pass (+1 lines)
Lines 1-2 Link Here
1
Add import for java.util.Collections
1
Add import for java.util.Collections
2
Add import for java.util.LinkedList
2
Add import for java.util.LinkedList
3
Add static import for java.util.Collections.emptyList
(-)3662dc3ca4aa (+1 lines)
Added Link Here
1
Add import for java.util.Calendar
(-)3662dc3ca4aa (+1 lines)
Added Link Here
1
Add import for javax.crypto.KeyAgreement
(-)3662dc3ca4aa (+1 lines)
Added Link Here
1
Add import for java.util.Collections
(-)3662dc3ca4aa (+2 lines)
Added Link Here
1
Add import for java.util.Collections
2
Add static import for java.util.Collections.emptySet
(-)3662dc3ca4aa (+10 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
import static java.util.Collections.emptySet;
4
5
public class ImportTestStatic4 {
6
7
    public ImportTestStatic4() {
8
        emptySet();
9
    }
10
}
(-)3662dc3ca4aa (+11 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
public class ImportTestStatic1 {
4
5
    public ImportTestStatic1() {
6
        Calendar.getInstance();
7
    }
8
9
    public void getInstance() {
10
    }
11
}
(-)3662dc3ca4aa (+11 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
import static java.util.Calendar.*;
4
5
public class ImportTestStatic2 {
6
7
    public ImportTestStatic2() throws Exception {
8
        getInstance();
9
        KeyAgreement.getInstance("");
10
    }
11
}
(-)3662dc3ca4aa (+8 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
public class ImportTestStatic3 {
4
5
    public ImportTestStatic3() throws Exception {
6
        Collections.doesNotExist();
7
    }
8
}
(-)3662dc3ca4aa (+8 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
public class ImportTestStatic4 {
4
5
    public ImportTestStatic4() {
6
        Collections.emptySet();
7
    }
8
}
(-)3662dc3ca4aa (+9 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
public class StaticImportTest1 {
4
5
    void doStuff() {
6
        // should change identifier and import
7
        Math.abs(1);
8
    }
9
}
(-)3662dc3ca4aa (+12 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
public class StaticImportTest2 {
4
5
    void doStuff() {
6
        // should only change identifier, no import
7
        StaticImportTest2.getLogger();
8
    }
9
10
    public static void getLogger() {
11
    }
12
}
(-)3662dc3ca4aa (+15 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
public class StaticImportTest3 extends Foo {
4
5
    void doStuff() {
6
        // should only change identifier, no import
7
        Foo.foo();
8
    }
9
}
10
11
class Foo {
12
13
    static protected void foo() {
14
    }
15
}
(-)3662dc3ca4aa (+12 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
import java.util.Calendar;
4
import static java.util.Calendar.*;
5
6
public class StaticImportTest4 {
7
8
    void doStuff() {
9
        // should only change identifier, no import
10
        Calendar.getInstance();
11
    }
12
}
(-)3662dc3ca4aa (+14 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
import java.util.logging.Logger;
4
5
public class StaticImportTest5 {
6
7
    void doStuff() {
8
        // should not offer a static import, name clash with local
9
        Logger.getLogger("");
10
    }
11
12
    public static void getLogger() {
13
    }
14
}
(-)3662dc3ca4aa (+21 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
public class StaticImportTest6 extends Foo {
4
5
    void doStuff() {
6
        // should not offer a static import, name clash with inherited
7
        Bar.foo();
8
    }
9
}
10
11
class Foo {
12
13
    static protected void foo() {
14
    }
15
}
16
17
class Bar {
18
19
    static protected void foo() {
20
    }
21
}
(-)3662dc3ca4aa (+12 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
import javax.crypto.KeyAgreement;
4
import static java.util.Calendar.*;
5
6
public class StaticImportTest7 {
7
8
    void doStuff() throws Exception {
9
        // should not offer a static import, name clash with imported
10
        KeyAgreement.getInstance("");
11
    }
12
}
(-)3662dc3ca4aa (+18 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
public class StaticImportTest8 extends Foo {
4
5
    class FooBar {
6
7
        void doOtherStuff() {
8
            // should only change identifier, no import
9
            Foo.foo();
10
        }
11
    }
12
}
13
14
class Foo {
15
16
    static protected void foo() {
17
    }
18
}
(-)3662dc3ca4aa (+24 lines)
Added Link Here
1
package org.netbeans.test.java.hints;
2
3
public class StaticImportTest9 extends Foo {
4
5
    class FooBar {
6
7
        void doOtherStuff() {
8
            // should not offer a static import, name clash with inherited
9
            Bar.foo();
10
        }
11
    }
12
}
13
14
class Foo {
15
16
    static protected void foo() {
17
    }
18
}
19
20
class Bar {
21
22
    static protected void foo() {
23
    }
24
}
(-)3662dc3ca4aa (+46 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
package org.netbeans.modules.java.hints;
25
26
/**
27
 *
28
 * @author Samuel Halliday
29
 */
30
public class StaticImportTest {
31
32
33
    public void testStaticImportHint1() throws Exception {
34
        //performTest("StaticImportTest1", "static import", 7, 16);
35
        /*
36
         * XXX I created StaticImportTest[1-9] in the Unit Test Data folder, but it doesn't work
37
         * using the HintsTestBase pattern (but ImportClassTest does). I suspect this is because
38
         * HintsTestBase only works for errors, not same-line hints. I also tried looking at the
39
         * following, but with no success:-
40
         *
41
         * - ErrorHintsTestBase
42
         * - TreeRuleTestBase
43
         */
44
45
    }
46
}
(-)a/java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/ImportClassTest.java (-4 / +19 lines)
Lines 74-82 Link Here
74
    }
74
    }
75
    
75
    
76
    public void testImportHint4() throws Exception {
76
    public void testImportHint4() throws Exception {
77
        performTest("ImportTest4", "java.util.Collections", 7, 13);
77
        performTest("ImportTest4", "Add import for java.util.Collections", 7, 13);
78
    }
78
    }
79
    
79
80
    public void testImportHint5() throws Exception {
80
    public void testImportHint5() throws Exception {
81
        performTest("ImportTest5", "java.util.Map", 7, 13);
81
        performTest("ImportTest5", "java.util.Map", 7, 13);
82
    }
82
    }
Lines 84-90 Link Here
84
    public void testImportHint6() throws Exception {
84
    public void testImportHint6() throws Exception {
85
        performTest("ImportTest6", "java.util.Collections", 7, 13);
85
        performTest("ImportTest6", "java.util.Collections", 7, 13);
86
    }
86
    }
87
    
87
88
    public void testImportHintStatic1() throws Exception {
89
        performTestDoNotPerform("ImportTestStatic1", 6, 13);
90
    }
91
92
    public void testImportHintStatic2() throws Exception {
93
        performTestDoNotPerform("ImportTestStatic2", 9, 15);
94
    }
95
96
    public void testImportHintStatic3() throws Exception {
97
        performTestDoNotPerform("ImportTestStatic3", 6, 14);
98
    }
99
100
    public void testImportHintStatic4() throws Exception {
101
        performTest("ImportTestStatic4", "static import", 6, 15);
102
    }
103
88
    public void testImportHintDoNotPropose() throws Exception {
104
    public void testImportHintDoNotPropose() throws Exception {
89
        performTestDoNotPerform("ImportHintDoNotPropose", 10, 24);
105
        performTestDoNotPerform("ImportHintDoNotPropose", 10, 24);
90
        performTestDoNotPerform("ImportHintDoNotPropose", 11, 24);
106
        performTestDoNotPerform("ImportHintDoNotPropose", 11, 24);
Lines 107-111 Link Here
107
    protected String layer() {
123
    protected String layer() {
108
        return "org/netbeans/modules/java/hints/errors/only-imports-layer.xml";
124
        return "org/netbeans/modules/java/hints/errors/only-imports-layer.xml";
109
    }
125
    }
110
    
111
}
126
}

Return to bug 89258