This is an automated email from the ASF dual-hosted git repository.

jlahoda pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 731e7c9e05 Adding an option to disable unused hint for package private 
elements, ignoring elements that possibly are looked up using 
MethodHandles.Lookup.
     new c649c82879 Merge pull request #5173 from jlahoda/unused-improvements
731e7c9e05 is described below

commit 731e7c9e05f38ee7950bf32150391d5ca2cc474a
Author: Jan Lahoda <[email protected]>
AuthorDate: Sun Jan 1 09:21:22 2023 +0100

    Adding an option to disable unused hint for package private elements, 
ignoring elements that possibly are looked up using MethodHandles.Lookup.
---
 .../java/editor/base/semantic/UnusedDetector.java  |  88 +++++++-
 .../editor/base/semantic/UnusedDetectorTest.java   | 225 +++++++++++++++++++++
 .../netbeans/modules/java/hints/bugs/Unused.java   |  14 +-
 .../modules/java/hints/bugs/UnusedTest.java        |  20 ++
 4 files changed, 335 insertions(+), 12 deletions(-)

diff --git 
a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/UnusedDetector.java
 
b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/UnusedDetector.java
index d5a7cadce4..6e2e28e46f 100644
--- 
a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/UnusedDetector.java
+++ 
b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/UnusedDetector.java
@@ -22,15 +22,19 @@ import com.sun.source.tree.AssignmentTree;
 import com.sun.source.tree.ClassTree;
 import com.sun.source.tree.CompoundAssignmentTree;
 import com.sun.source.tree.EnhancedForLoopTree;
+import com.sun.source.tree.ExpressionTree;
 import com.sun.source.tree.IdentifierTree;
+import com.sun.source.tree.LiteralTree;
 import com.sun.source.tree.MemberReferenceTree;
 import com.sun.source.tree.MemberSelectTree;
+import com.sun.source.tree.MethodInvocationTree;
 import com.sun.source.tree.MethodTree;
 import com.sun.source.tree.NewClassTree;
 import com.sun.source.tree.Tree;
 import com.sun.source.tree.Tree.Kind;
 import com.sun.source.tree.VariableTree;
 import com.sun.source.util.TreePath;
+import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -76,11 +80,13 @@ public class UnusedDetector {
     public static class UnusedDescription {
         public final Element unusedElement;
         public final TreePath unusedElementPath;
+        public final boolean packagePrivate;
         public final UnusedReason reason;
 
-        public UnusedDescription(Element unusedElement, TreePath 
unusedElementPath, UnusedReason reason) {
+        public UnusedDescription(Element unusedElement, TreePath 
unusedElementPath, boolean packagePrivate, UnusedReason reason) {
             this.unusedElement = unusedElement;
             this.unusedElementPath = unusedElementPath;
+            this.packagePrivate = packagePrivate;
             this.reason = reason;
         }
 
@@ -118,39 +124,39 @@ public class UnusedDetector {
                 boolean isWritten = uses.contains(UseTypes.WRITTEN);
                 boolean isRead = uses.contains(UseTypes.READ);
                 if (!isWritten && !isRead) {
-                    result.add(new UnusedDescription(el, declaration, 
UnusedReason.NOT_WRITTEN_READ));
+                    result.add(new UnusedDescription(el, declaration, 
isPkgPrivate, UnusedReason.NOT_WRITTEN_READ));
                 } else if (!isWritten) {
-                    result.add(new UnusedDescription(el, declaration, 
UnusedReason.NOT_WRITTEN));
+                    result.add(new UnusedDescription(el, declaration, 
isPkgPrivate, UnusedReason.NOT_WRITTEN));
                 } else if (!isRead) {
-                    result.add(new UnusedDescription(el, declaration, 
UnusedReason.NOT_READ));
+                    result.add(new UnusedDescription(el, declaration, 
isPkgPrivate, UnusedReason.NOT_READ));
                 }
             } else if (el.getKind().isField() && (isPrivate || isPkgPrivate)) {
-                if (!isSerialSpecField(info, el)) {
+                if (!isSerialSpecField(info, el) && !lookedUpElement(el, 
uv.type2LookedUpFields, uv.allStringLiterals)) {
                     boolean isWritten = uses.contains(UseTypes.WRITTEN);
                     boolean isRead = uses.contains(UseTypes.READ);
                     if (!isWritten && !isRead) {
                         if (isPrivate || isUnusedInPkg(info, el, cancel)) {
-                            result.add(new UnusedDescription(el, declaration, 
UnusedReason.NOT_WRITTEN_READ));
+                            result.add(new UnusedDescription(el, declaration, 
isPkgPrivate, UnusedReason.NOT_WRITTEN_READ));
                         }
                     } else if (!isWritten) {
-                        result.add(new UnusedDescription(el, declaration, 
UnusedReason.NOT_WRITTEN));
+                        result.add(new UnusedDescription(el, declaration, 
isPkgPrivate, UnusedReason.NOT_WRITTEN));
                     } else if (!isRead) {
                         if (isPrivate || isUnusedInPkg(info, el, cancel)) {
-                            result.add(new UnusedDescription(el, declaration, 
UnusedReason.NOT_READ));
+                            result.add(new UnusedDescription(el, declaration, 
isPkgPrivate, UnusedReason.NOT_READ));
                         }
                     }
                 }
             } else if ((el.getKind() == ElementKind.CONSTRUCTOR || 
el.getKind() == ElementKind.METHOD) && (isPrivate || isPkgPrivate)) {
                 if (!isSerializationMethod(info, (ExecutableElement)el) && 
!uses.contains(UseTypes.USED)
-                        && 
!info.getElementUtilities().overridesMethod((ExecutableElement)el)) {
+                        && 
!info.getElementUtilities().overridesMethod((ExecutableElement)el) && 
!lookedUpElement(el, uv.type2LookedUpMethods, uv.allStringLiterals)) {
                     if (isPrivate || isUnusedInPkg(info, el, cancel)) {
-                        result.add(new UnusedDescription(el, declaration, 
UnusedReason.NOT_USED));
+                        result.add(new UnusedDescription(el, declaration, 
isPkgPrivate, UnusedReason.NOT_USED));
                     }
                 }
             } else if ((el.getKind().isClass() || el.getKind().isInterface()) 
&& (isPrivate || isPkgPrivate)) {
                 if (!uses.contains(UseTypes.USED)) {
                     if (isPrivate || isUnusedInPkg(info, el, cancel)) {
-                        result.add(new UnusedDescription(el, declaration, 
UnusedReason.NOT_USED));
+                        result.add(new UnusedDescription(el, declaration, 
isPkgPrivate, UnusedReason.NOT_USED));
                     }
                 }
             }
@@ -280,6 +286,17 @@ public class UnusedDetector {
                LOCAL_VARIABLES.contains(el.getKind());
     }
 
+    private static boolean lookedUpElement(Element element, Map<Element, 
Set<String>> type2LookedUp, Set<String> allStringLiterals) {
+        String name = element.getKind() == ElementKind.CONSTRUCTOR ? "<init>" 
: element.getSimpleName().toString();
+        return isLookedUp(element.getEnclosingElement(), name, type2LookedUp, 
allStringLiterals) ||
+               isLookedUp(null, name, type2LookedUp, allStringLiterals);
+    }
+
+    private static boolean isLookedUp(Element owner, String name, Map<Element, 
Set<String>> type2LookedUp, Set<String> allStringLiterals) {
+        Set<String> lookedUp = type2LookedUp.getOrDefault(owner, 
Collections.emptySet());
+        return lookedUp.contains(name) || (allStringLiterals.contains(name) && 
lookedUp.contains(null));
+    }
+
     private static boolean isUnusedInPkg(CompilationInfo info, Element el, 
Callable<Boolean> cancel) {
         TypeElement typeElement;
         Set<? extends String> packageSet = 
Collections.singleton(info.getElements().getPackageOf(el).getQualifiedName().toString());
@@ -389,11 +406,16 @@ public class UnusedDetector {
 
         private final Map<Element, Set<UseTypes>> useTypes = new HashMap<>();
         private final Map<Element, TreePath> element2Declaration = new 
HashMap<>();
+        private final Map<Element, Set<String>> type2LookedUpMethods = new 
HashMap<>();
+        private final Map<Element, Set<String>> type2LookedUpFields = new 
HashMap<>();
+        private final Set<String> allStringLiterals = new HashSet<>();
+        private final TypeElement methodHandlesLookup;
         private final CompilationInfo info;
         private ExecutableElement recursionDetector;
 
         public UnusedVisitor(CompilationInfo info) {
             this.info = info;
+            this.methodHandlesLookup = 
info.getElements().getTypeElement(MethodHandles.Lookup.class.getCanonicalName());
         }
 
         @Override
@@ -597,5 +619,49 @@ public class UnusedDetector {
                 }
             }
         }
+
+        @Override
+        public Void visitLiteral(LiteralTree node, Void p) {
+            if (node.getKind() == Kind.STRING_LITERAL) {
+                allStringLiterals.add((String) ((LiteralTree) 
node).getValue());
+            }
+            return super.visitLiteral(node, p);
+        }
+
+        @Override
+        public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
+            Element invoked = info.getTrees().getElement(new 
TreePath(getCurrentPath(), node.getMethodSelect()));
+            if (invoked != null && invoked.getEnclosingElement() == 
methodHandlesLookup && node.getArguments().size() > 0) {
+                ExpressionTree clazz = node.getArguments().get(0);
+                Element lookupType = null;
+                if (clazz.getKind() == Kind.MEMBER_SELECT) {
+                    MemberSelectTree mst = (MemberSelectTree) clazz;
+                    if (mst.getIdentifier().contentEquals("class")) {
+                        lookupType = info.getTrees().getElement(new 
TreePath(new TreePath(getCurrentPath(), clazz), mst.getExpression()));
+                    }
+                }
+                String lookupName = null;
+                if (node.getArguments().size() > 1) {
+                    ExpressionTree name  = node.getArguments().get(1);
+                    if (name.getKind() == Kind.STRING_LITERAL) {
+                        lookupName = (String) ((LiteralTree) name).getValue();
+                    }
+                }
+                switch (invoked.getSimpleName().toString()) {
+                    case "findStatic": case "findVirtual": case "findSpecial":
+                        type2LookedUpMethods.computeIfAbsent(lookupType, t -> 
new HashSet<>()).add(lookupName);
+                        break;
+                    case "findConstructor":
+                        type2LookedUpMethods.computeIfAbsent(lookupType, t -> 
new HashSet<>()).add("<init>");
+                        break;
+                    case "findGetter": case "findSetter": case 
"findStaticGetter":
+                    case "findStaticSetter": case "findStaticVarHandle": case 
"findVarHandle":
+                        type2LookedUpFields.computeIfAbsent(lookupType, t -> 
new HashSet<>()).add(lookupName);
+                        break;
+                }
+            }
+            return super.visitMethodInvocation(node, p);
+        }
+
     }
 }
diff --git 
a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/UnusedDetectorTest.java
 
b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/UnusedDetectorTest.java
index a94df908b7..d62fbd9b97 100644
--- 
a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/UnusedDetectorTest.java
+++ 
b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/UnusedDetectorTest.java
@@ -302,6 +302,231 @@ public class UnusedDetectorTest extends NbTestCase {
                     "3:<init>:NOT_USED");
     }
 
+    @Test
+    public void testNoUnusedWhenLookup() throws Exception {
+        performTest("test/Test.java",
+                    "package test;\n" +
+                    "import java.lang.invoke.MethodHandles.Lookup;\n" +
+                    "public class Test implements I {\n" +
+                    "    public void lookup(Lookup l) {\n" +
+                    "        l.findConstructor(T1.class, null);\n" +
+                    "        l.findSpecial(Test.class, \"test1\", null, 
null);\n" +
+                    "        l.findStatic(Test.class, \"test3\", null);\n" +
+                    "        l.findVirtual(Test.class, \"test5\", null);\n" +
+                    "        l.findStaticGetter(Test.class, \"f1\", null);\n" +
+                    "        l.findStaticSetter(Test.class, \"f2\", null);\n" +
+                    "        l.findStaticVarHandle(Test.class, \"f3\", 
null);\n" +
+                    "        l.findGetter(Test.class, \"f5\", null);\n" +
+                    "        l.findSetter(Test.class, \"f6\", null);\n" +
+                    "        l.findVarHandle(Test.class, \"f7\", null);\n" +
+                    "    }\n" +
+                    "    private static void test1() {\n" +
+                    "    }\n" +
+                    "    private static void test2() {\n" +
+                    "    }\n" +
+                    "    private static void test3() {\n" +
+                    "    }\n" +
+                    "    private static void test4() {\n" +
+                    "    }\n" +
+                    "    private void test5() {\n" +
+                    "    }\n" +
+                    "    private void test6() {\n" +
+                    "    }\n" +
+                    "    public class T1 {\n" +
+                    "        private T1(int i) { System.err.println(i); }\n" +
+                    "    }\n" +
+                    "    public class T2 {\n" +
+                    "        private T2(int i) { System.err.println(i); }\n" +
+                    "    }\n" +
+                    "    private static int f1;\n" +
+                    "    private static int f2;\n" +
+                    "    private static int f3;\n" +
+                    "    private static int f4;\n" +
+                    "    private int f5;\n" +
+                    "    private int f6;\n" +
+                    "    private int f7;\n" +
+                    "    private int f8;\n" +
+                    "}\n" +
+                    "interface I {}\n" +
+                    "}\n",
+                    "18:test2:NOT_USED",
+                    "22:test4:NOT_USED",
+                    "26:test6:NOT_USED",
+                    "32:<init>:NOT_USED",
+                    "37:f4:NOT_READ",
+                    "41:f8:NOT_READ");
+    }
+
+    @Test
+    public void testNoUnusedWhenLookupNoLiterals() throws Exception {
+        performTest("test/Test.java",
+                    "package test;\n" +
+                    "import java.lang.invoke.MethodHandles.Lookup;\n" +
+                    "public class Test implements I {\n" +
+                    "    public void lookup(Lookup l, String name) {\n" +
+                    "        doLookup(l, \"test1\");\n" +
+                    "        doLookup(l, \"test3\");\n" +
+                    "        doLookup(l, \"test5\");\n" +
+                    "        doLookup(l, \"f1\");\n" +
+                    "        doLookup(l, \"f2\");\n" +
+                    "        doLookup(l, \"f3\");\n" +
+                    "        doLookup(l, \"f5\");\n" +
+                    "        doLookup(l, \"f6\");\n" +
+                    "        doLookup(l, \"f7\");\n" +
+                    "    }\n" +
+                    "    public void doLookup(Lookup l, String name) {\n" +
+                    "        l.findSpecial(Test.class, name, null, null);\n" +
+                    "        l.findStatic(Test.class, name, null);\n" +
+                    "        l.findVirtual(Test.class, name, null);\n" +
+                    "        l.findStaticGetter(Test.class, name, null);\n" +
+                    "        l.findStaticSetter(Test.class, name, null);\n" +
+                    "        l.findStaticVarHandle(Test.class, name, null);\n" 
+
+                    "        l.findGetter(Test.class, name, null);\n" +
+                    "        l.findSetter(Test.class, name, null);\n" +
+                    "        l.findVarHandle(Test.class, name, null);\n" +
+                    "    }\n" +
+                    "    private static void test1() {\n" +
+                    "    }\n" +
+                    "    private static void test2() {\n" +
+                    "    }\n" +
+                    "    private static void test3() {\n" +
+                    "    }\n" +
+                    "    private static void test4() {\n" +
+                    "    }\n" +
+                    "    private void test5() {\n" +
+                    "    }\n" +
+                    "    private void test6() {\n" +
+                    "    }\n" +
+                    "    private static int f1;\n" +
+                    "    private static int f2;\n" +
+                    "    private static int f3;\n" +
+                    "    private static int f4;\n" +
+                    "    private int f5;\n" +
+                    "    private int f6;\n" +
+                    "    private int f7;\n" +
+                    "    private int f8;\n" +
+                    "}\n" +
+                    "interface I {}\n" +
+                    "}\n",
+                    "28:test2:NOT_USED",
+                    "32:test4:NOT_USED",
+                    "36:test6:NOT_USED",
+                    "41:f4:NOT_READ",
+                    "45:f8:NOT_READ");
+    }
+
+    @Test
+    public void testNoUnusedWhenLookupNoClass() throws Exception {
+        performTest("test/Test.java",
+                    "package test;\n" +
+                    "import java.lang.invoke.MethodHandles.Lookup;\n" +
+                    "public class Test implements I {\n" +
+                    "    public void lookup(Lookup l, Class<?> c) {\n" +
+                    "        l.findConstructor(c, null);\n" +
+                    "        l.findSpecial(c, \"test1\", null, null);\n" +
+                    "        l.findStatic(c, \"test3\", null);\n" +
+                    "        l.findVirtual(c, \"test5\", null);\n" +
+                    "        l.findStaticGetter(c, \"f1\", null);\n" +
+                    "        l.findStaticSetter(c, \"f2\", null);\n" +
+                    "        l.findStaticVarHandle(c, \"f3\", null);\n" +
+                    "        l.findGetter(c, \"f5\", null);\n" +
+                    "        l.findSetter(c, \"f6\", null);\n" +
+                    "        l.findVarHandle(c, \"f7\", null);\n" +
+                    "    }\n" +
+                    "    private static void test1() {\n" +
+                    "    }\n" +
+                    "    private static void test2() {\n" +
+                    "    }\n" +
+                    "    private static void test3() {\n" +
+                    "    }\n" +
+                    "    private static void test4() {\n" +
+                    "    }\n" +
+                    "    private void test5() {\n" +
+                    "    }\n" +
+                    "    private void test6() {\n" +
+                    "    }\n" +
+                    "    public class T1 {\n" +
+                    "        private T1(int i) { System.err.println(i); }\n" +
+                    "    }\n" +
+                    "    public class T2 {\n" +
+                    "        private T2(int i) { System.err.println(i); }\n" +
+                    "    }\n" +
+                    "    private static int f1;\n" +
+                    "    private static int f2;\n" +
+                    "    private static int f3;\n" +
+                    "    private static int f4;\n" +
+                    "    private int f5;\n" +
+                    "    private int f6;\n" +
+                    "    private int f7;\n" +
+                    "    private int f8;\n" +
+                    "}\n" +
+                    "interface I {}\n" +
+                    "}\n",
+                    "18:test2:NOT_USED",
+                    "22:test4:NOT_USED",
+                    "26:test6:NOT_USED",
+                    "37:f4:NOT_READ",
+                    "41:f8:NOT_READ");
+    }
+
+    @Test
+    public void testUnusedWhenNoLookup() throws Exception {
+        performTest("test/Test.java",
+                    "package test;\n" +
+                    "public class Test implements I {\n" +
+                    "    public void lookup() {\n" +
+                    "        String[] s = new String[] {\n" +
+                    "            \"test1\",\n" +
+                    "            \"test3\",\n" +
+                    "            \"test5\",\n" +
+                    "            \"f1\",\n" +
+                    "            \"f5\",\n" +
+                    "        };\n" +
+                    "    }\n" +
+                    "    private static void test1() {\n" +
+                    "    }\n" +
+                    "    private static void test3() {\n" +
+                    "    }\n" +
+                    "    private void test5() {\n" +
+                    "    }\n" +
+                    "    public class T1 {\n" +
+                    "        private T1(int i) { System.err.println(i); }\n" +
+                    "    }\n" +
+                    "    private static int f1;\n" +
+                    "    private int f5;\n" +
+                    "}\n" +
+                    "interface I {}\n" +
+                    "}\n",
+                    "4:s:NOT_READ",
+                    "12:test1:NOT_USED",
+                    "14:test3:NOT_USED",
+                    "16:test5:NOT_USED",
+                    "19:<init>:NOT_USED",
+                    "21:f1:NOT_READ",
+                    "22:f5:NOT_READ");
+    }
+
+    @Test
+    public void testUnusedWhenDifferentClass() throws Exception {
+        performTest("test/Test.java",
+                    "package test;\n" +
+                    "import java.lang.invoke.MethodHandles.Lookup;\n" +
+                    "public class Test implements I {\n" +
+                    "    public void lookup(Lookup l) {\n" +
+                    "        l.findStatic(T1.class, \"test1\", null);\n" +
+                    "    }\n" +
+                    "    private static void test1() {\n" +
+                    "    }\n" +
+                    "    public class T1 {\n" +
+                    "        private static void test1() {\n" +
+                    "        }\n" +
+                    "    }\n" +
+                    "}\n" +
+                    "interface I {}\n" +
+                    "}\n",
+                    "7:test1:NOT_USED");
+    }
+
     protected String sourceLevel = "1.8";
 
     protected void performTest(String fileName, String code, String... 
expected) throws Exception {
diff --git 
a/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Unused.java 
b/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Unused.java
index 207bbf4e54..34744e9678 100644
--- a/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Unused.java
+++ b/java/java.hints/src/org/netbeans/modules/java/hints/bugs/Unused.java
@@ -27,6 +27,7 @@ import 
org.netbeans.modules.java.editor.base.semantic.UnusedDetector;
 import 
org.netbeans.modules.java.editor.base.semantic.UnusedDetector.UnusedDescription;
 import org.netbeans.spi.editor.hints.ErrorDescription;
 import org.netbeans.spi.editor.hints.Fix;
+import org.netbeans.spi.java.hints.BooleanOption;
 import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
 import org.netbeans.spi.java.hints.Hint;
 import org.netbeans.spi.java.hints.HintContext;
@@ -41,18 +42,29 @@ import org.openide.util.NbBundle.Messages;
 @Hint(displayName = "#DN_org.netbeans.modules.java.hints.bugs.Unused", 
description = "#DESC_org.netbeans.modules.java.hints.bugs.Unused", 
category="bugs", options=Hint.Options.QUERY, suppressWarnings="unused")
 @Messages({
     "DN_org.netbeans.modules.java.hints.bugs.Unused=Unused Element",
-    "DESC_org.netbeans.modules.java.hints.bugs.Unused=Detects and reports 
unused variables, methods and classes"
+    "DESC_org.netbeans.modules.java.hints.bugs.Unused=Detects and reports 
unused variables, methods and classes",
+    "LBL_UnusedPackagePrivate=Also detect unused package private elements",
+    "TP_UnusedPackagePrivate=Will also detect package private elements that 
are unused"
 })
 public class Unused {
 
+    private static final boolean DETECT_UNUSED_PACKAGE_PRIVATE_DEFAULT = true;
+
+    @BooleanOption(displayName="#LBL_UnusedPackagePrivate", 
tooltip="#TP_UnusedPackagePrivate", 
defaultValue=DETECT_UNUSED_PACKAGE_PRIVATE_DEFAULT)
+    public static final String DETECT_UNUSED_PACKAGE_PRIVATE = 
"detect.unused.package.private";
+
     @TriggerTreeKind(Kind.COMPILATION_UNIT)
     public static List<ErrorDescription> unused(HintContext ctx) {
         List<UnusedDescription> unused = 
UnusedDetector.findUnused(ctx.getInfo(), () -> ctx.isCanceled());
         List<ErrorDescription> result = new ArrayList<>(unused.size());
+        boolean detectUnusedPackagePrivate = 
ctx.getPreferences().getBoolean(DETECT_UNUSED_PACKAGE_PRIVATE, 
DETECT_UNUSED_PACKAGE_PRIVATE_DEFAULT);
         for (UnusedDescription ud : unused) {
             if (ctx.isCanceled()) {
                 break;
             }
+            if (!detectUnusedPackagePrivate && ud.packagePrivate) {
+                continue;
+            }
             ErrorDescription err = convertUnused(ctx, ud);
             if (err != null) {
                 result.add(err);
diff --git 
a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnusedTest.java
 
b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnusedTest.java
index b00212fe31..e924a4183b 100644
--- 
a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnusedTest.java
+++ 
b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/UnusedTest.java
@@ -65,4 +65,24 @@ public class UnusedTest extends NbTestCase {
                 .findWarning("3:35-3:36:verifier:Variable s is never read")
                 .assertFixes();
     }
+
+    public void testUnusedNoPackagePrivate() throws Exception {
+        HintTest
+                .create()
+                .input("package test;\n" +
+                       "public class Test {\n" +
+                       "    void packagePrivate() {}\n" +
+                       "}\n")
+                .run(Unused.class)
+                .assertWarnings("2:9-2:23:verifier:" + 
Bundle.ERR_NotUsed("packagePrivate"));
+        HintTest
+                .create()
+                .preference(Unused.DETECT_UNUSED_PACKAGE_PRIVATE, false)
+                .input("package test;\n" +
+                       "public class Test {\n" +
+                       "    void packagePrivate() {}\n" +
+                       "}\n")
+                .run(Unused.class)
+                .assertWarnings();
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to