diff -r 3662dc3ca4aa java.hints/src/org/netbeans/modules/java/hints/Bundle.properties --- a/java.hints/src/org/netbeans/modules/java/hints/Bundle.properties Sat May 02 01:13:49 2009 +0200 +++ b/java.hints/src/org/netbeans/modules/java/hints/Bundle.properties Sat May 02 19:47:54 2009 +0100 @@ -76,7 +76,7 @@ LBL_Imports_EXCLUDED=Import from Excluded LBL_Imports_STAR=Star import -DSC_Imports_DELAGATE=Delegate - non GUI +DSC_Imports_DELEGATE=Delegate - non GUI DSC_Imports_UNUSED=Unused Import DSC_Imports_DUPLICATE=Multiple Import DSC_Imports_SAME_PACKAGE=Import From The Same Package @@ -263,6 +263,12 @@ ERR_SynchronizationOnNonFinalField=Synchronization on non-final field DN_SynchronizationOnNonFinalField=Synchronization on non-final field +HINT_StaticImport=Convert method to static import +HINT_StaticImport2=Add static import for {0} +DSC_StaticImport=Convert method to static import +ERR_StaticImport=Convert method to static import +DN_StaticImport=Convert method to static import + HINT_SuspiciousCall=Suspicious call to {0}:\nExpected type {2}, actual type {1} HINT_SuspiciousCallIncompatibleTypes=Suspicious call to {0}:\nGiven object cannot contain instances of {1} (expected {2}) DN_CollectionRemove=Suspicous method call diff -r 3662dc3ca4aa java.hints/src/org/netbeans/modules/java/hints/StaticImport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/src/org/netbeans/modules/java/hints/StaticImport.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,346 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * Contributor(s): + * + * Portions Copyrighted 2009 Sun Microsystems, Inc. + */ +package org.netbeans.modules.java.hints; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.ImportTree; +import com.sun.source.tree.MethodInvocationTree; +import com.sun.source.tree.Tree.Kind; +import com.sun.source.util.TreePath; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; +import org.netbeans.api.java.source.CompilationInfo; +import org.netbeans.api.java.source.ElementUtilities; +import org.netbeans.api.java.source.JavaSource; +import org.netbeans.api.java.source.JavaSource.Phase; +import org.netbeans.api.java.source.SourceUtils; +import org.netbeans.api.java.source.Task; +import org.netbeans.api.java.source.TreeMaker; +import org.netbeans.api.java.source.TreePathHandle; +import org.netbeans.api.java.source.WorkingCopy; +import org.netbeans.modules.java.hints.spi.AbstractHint; +import org.netbeans.spi.editor.hints.ChangeInfo; +import org.netbeans.spi.editor.hints.ErrorDescription; +import org.netbeans.spi.editor.hints.ErrorDescriptionFactory; +import org.netbeans.spi.editor.hints.Fix; +import org.openide.util.NbBundle; +import static org.netbeans.modules.editor.java.Utilities.getElementName; + +/** + * Hint offering to convert a qualified static method into a static import. e.g. + * Math.abs(-1) -> abs(-1). + * + * @author Sam Halliday + * @see RFE 89258 + */ +public class StaticImport extends AbstractHint { + + private final AtomicBoolean cancel = new AtomicBoolean(); + + public StaticImport() { + super(true, false, HintSeverity.CURRENT_LINE_WARNING); + } + + @Override + public String getDescription() { + return NbBundle.getMessage(StaticImport.class, "DSC_StaticImport"); + } + + public Set getTreeKinds() { + return EnumSet.of(Kind.METHOD_INVOCATION); + } + + public List run(CompilationInfo info, TreePath treePath) { + if (treePath.getLeaf().getKind() != Kind.METHOD_INVOCATION) { + return null; + } + cancel.set(false); + MethodInvocationTree tree = (MethodInvocationTree) treePath.getLeaf(); + ExpressionTree identifier = tree.getMethodSelect(); + if (identifier.getKind() != Kind.MEMBER_SELECT) { + return null; + } + Element e = info.getTrees().getElement(new TreePath(treePath, identifier)); + if (e == null || !e.getModifiers().contains(Modifier.STATIC)) { + return null; + } + Element enclosingEl = e.getEnclosingElement(); + if (enclosingEl == null) { + return null; + } + // XXX is there a better way to ignore error cases + String sn = e.getSimpleName().toString(); + if (!isValidStaticMethod(info, getElementName(enclosingEl, true).toString(), sn)) { + return null; + } + // TODO ignore case where source code is less than Java 1.5 + Element klass = info.getTrees().getElement(getContainingClass(treePath)); + String fqn = null; + String fqn1 = getMethodFqn(e); + if (!isSubTypeOrInnerOfSubType(info, klass, enclosingEl) && !isStaticallyImported(info, fqn1)) { + if (hasMethodNameClash(info, klass, sn) || hasStaticImportSimpleNameClash(info, sn)) { + return null; + } + fqn = fqn1; + } + List fixes = Collections.singletonList(new FixImpl(TreePathHandle.create(treePath, info), fqn)); + String desc = NbBundle.getMessage(AddOverrideAnnotation.class, "HINT_StaticImport"); + int start = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), identifier); + int end = (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), identifier); + ErrorDescription ed = ErrorDescriptionFactory.createErrorDescription(getSeverity().toEditorSeverity(), desc, fixes, info.getFileObject(), start, end); + if (cancel.get()) { + return null; + } + return Collections.singletonList(ed); + } + + public String getId() { + return StaticImport.class.getName(); + } + + public String getDisplayName() { + return NbBundle.getMessage(StaticImport.class, "DSC_StaticImport"); + } + + public void cancel() { + cancel.set(true); + } + + public static final class FixImpl implements Fix, Task { + + private final TreePathHandle handle; + private final String fqn; + + /** + * @param handle to the METHOD_INVOCATION + * @param fqn to static import, or null to not perform any imports + */ + public FixImpl(TreePathHandle handle, String fqn) { + this.handle = handle; + this.fqn = fqn; + } + + public String getText() { + if (fqn == null) { + return NbBundle.getMessage(StaticImport.class, "HINT_StaticImport"); + } else { + return NbBundle.getMessage(StaticImport.class, "HINT_StaticImport2", fqn); + } + } + + public ChangeInfo implement() throws Exception { + JavaSource js = JavaSource.forFileObject(handle.getFileObject()); + js.runModificationTask(this).commit(); + return null; + } + + public void run(WorkingCopy copy) throws Exception { + if (copy.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) { + return; + } + TreePath treePath = handle.resolve(copy); + if (treePath == null || treePath.getLeaf().getKind() != Kind.METHOD_INVOCATION) { + return; + } + MethodInvocationTree tree = (MethodInvocationTree) treePath.getLeaf(); + ExpressionTree identifier = tree.getMethodSelect(); + Element e = copy.getTrees().getElement(new TreePath(treePath, identifier)); + if (e == null || !e.getModifiers().contains(Modifier.STATIC) || identifier.getKind() != Kind.MEMBER_SELECT) { + return; + } + TreeMaker make = copy.getTreeMaker(); + copy.rewrite(identifier, make.Identifier(e.getSimpleName())); + if (fqn == null) { + return; + } + CompilationUnitTree cut = copy.getCompilationUnit(); + CompilationUnitTree nue = SourceUtils.addStaticImports(cut, Collections.singletonList(fqn), make); + copy.rewrite(cut, nue); + } + } + + // returns true if a METHOD is enclosed in element with simple name sn + private static boolean hasMethodWithSimpleName(CompilationInfo info, Element element, final String sn) { + Iterable members = + info.getElementUtilities().getMembers(element.asType(), new ElementUtilities.ElementAcceptor() { + + public boolean accept(Element e, TypeMirror type) { + if (e.getKind() == ElementKind.METHOD && e.getSimpleName().toString().equals(sn)) { + return true; + } + return false; + } + }); + return members.iterator().hasNext(); + } + + /** + * @param info + * @param simpleName of static method. + * @return true if a static import exists with the same simple name. + * Caveat, expect false positives on protected and default visibility methods from wildcard static imports. + */ + public static boolean hasStaticImportSimpleNameClash(CompilationInfo info, String simpleName) { + for (ImportTree i : info.getCompilationUnit().getImports()) { + if (!i.isStatic()) { + continue; + } + String q = i.getQualifiedIdentifier().toString(); + if (q.endsWith(".*")) { //NOI18N + TypeElement ie = info.getElements().getTypeElement(q.substring(0, q.length() - 2)); + if (ie == null) { + continue; + } + for (Element enclosed : ie.getEnclosedElements()) { + Set modifiers = enclosed.getModifiers(); + if (enclosed.getKind() != ElementKind.METHOD || !modifiers.contains(Modifier.STATIC) || modifiers.contains(Modifier.PRIVATE)) { + continue; + } + String sn1 = enclosed.getSimpleName().toString(); + if (simpleName.equals(sn1)) { + return true; + } + } + } else { + int endIndex = q.lastIndexOf("."); //NOI18N + if (endIndex == -1 || endIndex >= q.length() - 1) { + continue; + } + if (q.substring(endIndex).equals(simpleName)) { + return true; + } + } + } + return false; + } + + /** + * @param info + * @param t1 + * @param t3 + * @return true iff the first type (or its containing class in the case of inner classes) + * is a subtype of the second. + * @see Types#isSubtype(javax.lang.model.type.TypeMirror, javax.lang.model.type.TypeMirror) + */ + private static boolean isSubTypeOrInnerOfSubType(CompilationInfo info, Element t1, Element t2) { + boolean isSubtype = info.getTypes().isSubtype(t1.asType(), t2.asType()); + boolean isInnerClass = t1.getEnclosingElement().getKind() == ElementKind.CLASS; + return isSubtype || (isInnerClass && info.getTypes().isSubtype(t1.getEnclosingElement().asType(), t2.asType())); + } + + /** + * @param info + * @param klass the element for a CLASS + * @param member the STATIC, MEMBER_SELECT Element for a MethodInvocationTree + * @return true if member has a simple name which would clash with local or inherited + * methods in klass (which may be an inner or static class). + */ + public static boolean hasMethodNameClash(CompilationInfo info, Element klass, String simpleName) { + assert klass != null; + assert klass.getKind() == ElementKind.CLASS; + + // check the members and inherited members of the klass + if (hasMethodWithSimpleName(info, klass, simpleName)) { + return true; + } + Element klassEnclosing = klass.getEnclosingElement(); + return (klassEnclosing != null && klassEnclosing.getKind() == ElementKind.CLASS && hasMethodWithSimpleName(info, klassEnclosing, simpleName)); + } + + /** + * @param e + * @return the FQN for a METHOD Element + */ + public static String getMethodFqn(Element e) { + // TODO: or alternatively, upgrade getElementName to handled METHOD + assert e.getKind() == ElementKind.METHOD; + return getElementName(e.getEnclosingElement(), true) + "." + e.getSimpleName(); + } + + /** + * @param tp + * @return the first path which is a CLASS or null if none found + */ + public static TreePath getContainingClass(TreePath tp) { + while (tp != null && tp.getLeaf().getKind() != Kind.CLASS) { + tp = tp.getParentPath(); + } + return tp; + } + + // return true if the fqn already has a static import + private static boolean isStaticallyImported(CompilationInfo info, String fqn) { + for (ImportTree i : info.getCompilationUnit().getImports()) { + if (!i.isStatic()) { + continue; + } + String q = i.getQualifiedIdentifier().toString(); + if (q.endsWith(".*") && fqn.startsWith(q.substring(0, q.length() - 1))) { //NOI18N + return true; + } + if (q.equals(fqn)) { + return true; + } + } + return false; + } + + /** + * @param info + * @param fqn of the containing class + * @param simpleName of the method + * @return true if {@code fqn.simpleName} represents a valid static method + */ + public static boolean isValidStaticMethod(CompilationInfo info, String fqn, String simpleName) { + TypeElement ie = info.getElements().getTypeElement(fqn); + if (ie == null) { + return false; + } + for (Element enclosed : ie.getEnclosedElements()) { + Set modifiers = enclosed.getModifiers(); + if (enclosed.getKind() != ElementKind.METHOD || !modifiers.contains(Modifier.STATIC) || modifiers.contains(Modifier.PRIVATE)) { + continue; + } + String sn1 = enclosed.getSimpleName().toString(); + if (simpleName.equals(sn1)) { + return true; + } + } + return false; + } +} diff -r 3662dc3ca4aa java.hints/src/org/netbeans/modules/java/hints/errors/ImportClass.java --- a/java.hints/src/org/netbeans/modules/java/hints/errors/ImportClass.java Sat May 02 01:13:49 2009 +0200 +++ b/java.hints/src/org/netbeans/modules/java/hints/errors/ImportClass.java Sat May 02 19:47:54 2009 +0100 @@ -43,6 +43,7 @@ import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.ImportTree; +import com.sun.source.tree.MemberSelectTree; import com.sun.source.tree.MethodInvocationTree; import com.sun.source.tree.Tree.Kind; import com.sun.source.util.TreePath; @@ -57,16 +58,19 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; +import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import org.netbeans.api.java.source.Task; import org.netbeans.api.java.source.CompilationInfo; import org.netbeans.api.java.source.JavaSource; import org.netbeans.api.java.source.JavaSource.Phase; +import org.netbeans.api.java.source.SourceUtils; +import org.netbeans.api.java.source.TreePathHandle; import org.netbeans.api.java.source.WorkingCopy; import org.netbeans.api.lexer.Token; import org.netbeans.modules.editor.java.Utilities; import org.netbeans.modules.java.editor.imports.ComputeImports; -import org.netbeans.modules.java.editor.imports.JavaFixAllImports; +import org.netbeans.modules.java.hints.StaticImport; import org.netbeans.modules.java.hints.errors.ImportClass.ImportCandidatesHolder; import org.netbeans.modules.java.hints.infrastructure.CreatorBasedLazyFixList; import org.netbeans.modules.java.hints.infrastructure.ErrorHintsProvider; @@ -164,6 +168,33 @@ List unfiltered = candidates.getB(); List fixes = new ArrayList(); + String staticSimpleName = null; + TreePath mitPath = null; + if (path.getLeaf().getKind() == Kind.IDENTIFIER) { + TreePath parent = path.getParentPath(); + if (parent != null && parent.getLeaf().getKind() == Kind.MEMBER_SELECT) { + mitPath = parent.getParentPath(); + if (mitPath != null && mitPath.getLeaf().getKind() == Kind.METHOD_INVOCATION) { + TreePath klass = StaticImport.getContainingClass(path); + Element klassElement = info.getTrees().getElement(klass); + // XXX why can't we use MemberSelectTree.getIdentifier + if (parent.getLeaf() instanceof MemberSelectTree) { + System.out.println("parent is MemberSelectTree"); + } else { + System.out.println("parent is NOT a MemberSelectTree"); + } + String ms = parent.getLeaf().toString(); + int i = ms.lastIndexOf("."); // NOI18N + if (i != -1 && i < ms.length() - 2) { + String sn = ms.substring(i + 1); + if (!StaticImport.hasMethodNameClash(info, klassElement, sn) && !StaticImport.hasStaticImportSimpleNameClash(info, sn)) { + staticSimpleName = sn; + } + } + } + } + } + if (unfiltered != null && filtered != null) { for (String fqn : unfiltered) { StringBuilder sort = new StringBuilder(); @@ -186,6 +217,13 @@ sort.append(fqn); fixes.add(new FixImport(file, fqn, sort.toString(), prefered)); + + if (staticSimpleName != null) { + String mFqn = fqn + "." + staticSimpleName; //NOI18N + if (StaticImport.isValidStaticMethod(info, fqn, staticSimpleName)) { + fixes.add(new StaticImport.FixImpl(TreePathHandle.create(mitPath, info), mFqn)); + } + } } } @@ -340,7 +378,7 @@ return ; } - CompilationUnitTree cut = JavaFixAllImports.addImports( + CompilationUnitTree cut = SourceUtils.addImports( copy.getCompilationUnit(), Collections.singletonList(te.getQualifiedName().toString()), copy.getTreeMaker() diff -r 3662dc3ca4aa java.hints/src/org/netbeans/modules/java/hints/resources/layer.xml --- a/java.hints/src/org/netbeans/modules/java/hints/resources/layer.xml Sat May 02 01:13:49 2009 +0200 +++ b/java.hints/src/org/netbeans/modules/java/hints/resources/layer.xml Sat May 02 19:47:54 2009 +0100 @@ -137,6 +137,7 @@ + diff -r 3662dc3ca4aa java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHint4-hints.pass --- a/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHint4-hints.pass Sat May 02 01:13:49 2009 +0200 +++ b/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHint4-hints.pass Sat May 02 19:47:54 2009 +0100 @@ -1,2 +1,3 @@ Add import for java.util.Collections Add import for java.util.LinkedList +Add static import for java.util.Collections.emptyList diff -r 3662dc3ca4aa java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHintStatic1-hints.pass --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHintStatic1-hints.pass Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,1 @@ +Add import for java.util.Calendar \ No newline at end of file diff -r 3662dc3ca4aa java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHintStatic2-hints.pass --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHintStatic2-hints.pass Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,1 @@ +Add import for javax.crypto.KeyAgreement \ No newline at end of file diff -r 3662dc3ca4aa java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHintStatic3-hints.pass --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHintStatic3-hints.pass Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,1 @@ +Add import for java.util.Collections \ No newline at end of file diff -r 3662dc3ca4aa java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHintStatic4-hints.pass --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHintStatic4-hints.pass Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,2 @@ +Add import for java.util.Collections +Add static import for java.util.Collections.emptySet diff -r 3662dc3ca4aa java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHintStatic4.pass --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/goldenfiles/org/netbeans/modules/java/hints/errors/ImportClassTest/testImportHintStatic4.pass Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,10 @@ +package org.netbeans.test.java.hints; + +import static java.util.Collections.emptySet; + +public class ImportTestStatic4 { + + public ImportTestStatic4() { + emptySet(); + } +} diff -r 3662dc3ca4aa java.hints/test/unit/data/org/netbeans/test/java/hints/ImportClassEnablerTest/ImportTestStatic1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/org/netbeans/test/java/hints/ImportClassEnablerTest/ImportTestStatic1.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,11 @@ +package org.netbeans.test.java.hints; + +public class ImportTestStatic1 { + + public ImportTestStatic1() { + Calendar.getInstance(); + } + + public void getInstance() { + } +} diff -r 3662dc3ca4aa java.hints/test/unit/data/org/netbeans/test/java/hints/ImportClassEnablerTest/ImportTestStatic2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/org/netbeans/test/java/hints/ImportClassEnablerTest/ImportTestStatic2.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,11 @@ +package org.netbeans.test.java.hints; + +import static java.util.Calendar.*; + +public class ImportTestStatic2 { + + public ImportTestStatic2() throws Exception { + getInstance(); + KeyAgreement.getInstance(""); + } +} diff -r 3662dc3ca4aa java.hints/test/unit/data/org/netbeans/test/java/hints/ImportClassEnablerTest/ImportTestStatic3.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/org/netbeans/test/java/hints/ImportClassEnablerTest/ImportTestStatic3.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,8 @@ +package org.netbeans.test.java.hints; + +public class ImportTestStatic3 { + + public ImportTestStatic3() throws Exception { + Collections.doesNotExist(); + } +} diff -r 3662dc3ca4aa java.hints/test/unit/data/org/netbeans/test/java/hints/ImportClassEnablerTest/ImportTestStatic4.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/org/netbeans/test/java/hints/ImportClassEnablerTest/ImportTestStatic4.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,8 @@ +package org.netbeans.test.java.hints; + +public class ImportTestStatic4 { + + public ImportTestStatic4() { + Collections.emptySet(); + } +} diff -r 3662dc3ca4aa java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest1.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,9 @@ +package org.netbeans.test.java.hints; + +public class StaticImportTest1 { + + void doStuff() { + // should change identifier and import + Math.abs(1); + } +} diff -r 3662dc3ca4aa java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest2.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,12 @@ +package org.netbeans.test.java.hints; + +public class StaticImportTest2 { + + void doStuff() { + // should only change identifier, no import + StaticImportTest2.getLogger(); + } + + public static void getLogger() { + } +} diff -r 3662dc3ca4aa java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest3.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest3.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,15 @@ +package org.netbeans.test.java.hints; + +public class StaticImportTest3 extends Foo { + + void doStuff() { + // should only change identifier, no import + Foo.foo(); + } +} + +class Foo { + + static protected void foo() { + } +} diff -r 3662dc3ca4aa java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest4.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest4.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,12 @@ +package org.netbeans.test.java.hints; + +import java.util.Calendar; +import static java.util.Calendar.*; + +public class StaticImportTest4 { + + void doStuff() { + // should only change identifier, no import + Calendar.getInstance(); + } +} diff -r 3662dc3ca4aa java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest5.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest5.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,14 @@ +package org.netbeans.test.java.hints; + +import java.util.logging.Logger; + +public class StaticImportTest5 { + + void doStuff() { + // should not offer a static import, name clash with local + Logger.getLogger(""); + } + + public static void getLogger() { + } +} diff -r 3662dc3ca4aa java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest6.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest6.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,21 @@ +package org.netbeans.test.java.hints; + +public class StaticImportTest6 extends Foo { + + void doStuff() { + // should not offer a static import, name clash with inherited + Bar.foo(); + } +} + +class Foo { + + static protected void foo() { + } +} + +class Bar { + + static protected void foo() { + } +} diff -r 3662dc3ca4aa java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest7.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest7.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,12 @@ +package org.netbeans.test.java.hints; + +import javax.crypto.KeyAgreement; +import static java.util.Calendar.*; + +public class StaticImportTest7 { + + void doStuff() throws Exception { + // should not offer a static import, name clash with imported + KeyAgreement.getInstance(""); + } +} diff -r 3662dc3ca4aa java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest8.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest8.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,18 @@ +package org.netbeans.test.java.hints; + +public class StaticImportTest8 extends Foo { + + class FooBar { + + void doOtherStuff() { + // should only change identifier, no import + Foo.foo(); + } + } +} + +class Foo { + + static protected void foo() { + } +} diff -r 3662dc3ca4aa java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest9.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/data/org/netbeans/test/java/hints/StaticImportTest9.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,24 @@ +package org.netbeans.test.java.hints; + +public class StaticImportTest9 extends Foo { + + class FooBar { + + void doOtherStuff() { + // should not offer a static import, name clash with inherited + Bar.foo(); + } + } +} + +class Foo { + + static protected void foo() { + } +} + +class Bar { + + static protected void foo() { + } +} diff -r 3662dc3ca4aa java.hints/test/unit/src/org/netbeans/modules/java/hints/StaticImportTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java.hints/test/unit/src/org/netbeans/modules/java/hints/StaticImportTest.java Sat May 02 19:47:54 2009 +0100 @@ -0,0 +1,46 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + */ +package org.netbeans.modules.java.hints; + +/** + * + * @author Samuel Halliday + */ +public class StaticImportTest { + + + public void testStaticImportHint1() throws Exception { + //performTest("StaticImportTest1", "static import", 7, 16); + /* + * XXX I created StaticImportTest[1-9] in the Unit Test Data folder, but it doesn't work + * using the HintsTestBase pattern (but ImportClassTest does). I suspect this is because + * HintsTestBase only works for errors, not same-line hints. I also tried looking at the + * following, but with no success:- + * + * - ErrorHintsTestBase + * - TreeRuleTestBase + */ + + } +} \ No newline at end of file diff -r 3662dc3ca4aa java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/ImportClassTest.java --- a/java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/ImportClassTest.java Sat May 02 01:13:49 2009 +0200 +++ b/java.hints/test/unit/src/org/netbeans/modules/java/hints/errors/ImportClassTest.java Sat May 02 19:47:54 2009 +0100 @@ -74,9 +74,9 @@ } public void testImportHint4() throws Exception { - performTest("ImportTest4", "java.util.Collections", 7, 13); + performTest("ImportTest4", "Add import for java.util.Collections", 7, 13); } - + public void testImportHint5() throws Exception { performTest("ImportTest5", "java.util.Map", 7, 13); } @@ -84,7 +84,23 @@ public void testImportHint6() throws Exception { performTest("ImportTest6", "java.util.Collections", 7, 13); } - + + public void testImportHintStatic1() throws Exception { + performTestDoNotPerform("ImportTestStatic1", 6, 13); + } + + public void testImportHintStatic2() throws Exception { + performTestDoNotPerform("ImportTestStatic2", 9, 15); + } + + public void testImportHintStatic3() throws Exception { + performTestDoNotPerform("ImportTestStatic3", 6, 14); + } + + public void testImportHintStatic4() throws Exception { + performTest("ImportTestStatic4", "static import", 6, 15); + } + public void testImportHintDoNotPropose() throws Exception { performTestDoNotPerform("ImportHintDoNotPropose", 10, 24); performTestDoNotPerform("ImportHintDoNotPropose", 11, 24); @@ -107,5 +123,4 @@ protected String layer() { return "org/netbeans/modules/java/hints/errors/only-imports-layer.xml"; } - }