This is an automated email from the ASF dual-hosted git repository.
dbalek 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 6b8e152d36 Do not mark test methods as unused.
new 35a3f1695c Merge pull request #6277 from
dbalek/dbalek/no-unused-test-methods
6b8e152d36 is described below
commit 6b8e152d36a9416928a5efcac23ece6ac2ec1976
Author: Dusan Balek <[email protected]>
AuthorDate: Mon Jul 31 15:26:40 2023 +0200
Do not mark test methods as unused.
---
java/java.editor.base/nbproject/project.xml | 8 +++
.../java/editor/base/semantic/UnusedDetector.java | 43 +++++++++++++---
.../netbeans/modules/java/hints/bugs/Unused.java | 1 -
java/junit.ui/nbproject/project.xml | 8 +++
.../junit/ui/actions/TestClassInfoTask.java | 29 ++++++++++-
java/spi.java.hints/apichanges.xml | 17 +++++++
java/spi.java.hints/nbproject/project.properties | 2 +-
java/spi.java.hints/nbproject/project.xml | 3 +-
.../spi/java/hints/unused/UsedDetector.java | 57 ++++++++++++++++++++++
9 files changed, 154 insertions(+), 14 deletions(-)
diff --git a/java/java.editor.base/nbproject/project.xml
b/java/java.editor.base/nbproject/project.xml
index d1ffc48275..8f79fbf993 100644
--- a/java/java.editor.base/nbproject/project.xml
+++ b/java/java.editor.base/nbproject/project.xml
@@ -122,6 +122,14 @@
<specification-version>1.87</specification-version>
</run-dependency>
</dependency>
+ <dependency>
+
<code-name-base>org.netbeans.spi.java.hints</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>1.56</specification-version>
+ </run-dependency>
+ </dependency>
<dependency>
<code-name-base>org.openide.filesystems</code-name-base>
<build-prerequisite/>
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 161855c43d..e129842e45 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
@@ -48,6 +48,8 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiFunction;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
@@ -69,8 +71,10 @@ import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.api.project.SourceGroup;
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
+import org.netbeans.spi.java.hints.unused.UsedDetector;
import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;
+import org.openide.util.Lookup;
/**
*
@@ -114,6 +118,18 @@ public class UnusedDetector {
UnusedVisitor uv = new UnusedVisitor(info);
uv.scan(info.getCompilationUnit(), null);
+ AtomicReference<List<UsedDetector>> usedDetectors = new
AtomicReference<>();
+ BiFunction<Element, TreePath, Boolean> markedAsUsed = (el, path) -> {
+ if (usedDetectors.get() == null) {
+ usedDetectors.set(collectUsedDetectors(info));
+ }
+ for (UsedDetector detector : usedDetectors.get()) {
+ if (detector.isUsed(el, path)) {
+ return true;
+ }
+ }
+ return false;
+ };
List<UnusedDescription> result = new ArrayList<>();
for (Entry<Element, TreePath> e : uv.element2Declaration.entrySet()) {
Element el = e.getKey();
@@ -124,11 +140,11 @@ public class UnusedDetector {
if (isLocalVariableClosure(el)) {
boolean isWritten = uses.contains(UseTypes.WRITTEN);
boolean isRead = uses.contains(UseTypes.READ);
- if (!isWritten && !isRead) {
+ if (!isWritten && !isRead && !markedAsUsed.apply(el,
declaration)) {
result.add(new UnusedDescription(el, declaration,
isPkgPrivate, UnusedReason.NOT_WRITTEN_READ));
- } else if (!isWritten) {
+ } else if (!isWritten && !markedAsUsed.apply(el, declaration))
{
result.add(new UnusedDescription(el, declaration,
isPkgPrivate, UnusedReason.NOT_WRITTEN));
- } else if (!isRead) {
+ } else if (!isRead && !markedAsUsed.apply(el, declaration)) {
result.add(new UnusedDescription(el, declaration,
isPkgPrivate, UnusedReason.NOT_READ));
}
} else if (el.getKind().isField() && (isPrivate || isPkgPrivate)) {
@@ -136,13 +152,13 @@ public class UnusedDetector {
boolean isWritten = uses.contains(UseTypes.WRITTEN);
boolean isRead = uses.contains(UseTypes.READ);
if (!isWritten && !isRead) {
- if (isPrivate || isUnusedInPkg(info, el, cancel)) {
+ if ((isPrivate || isUnusedInPkg(info, el, cancel)) &&
!markedAsUsed.apply(el, declaration)) {
result.add(new UnusedDescription(el, declaration,
isPkgPrivate, UnusedReason.NOT_WRITTEN_READ));
}
- } else if (!isWritten) {
+ } else if (!isWritten && !markedAsUsed.apply(el,
declaration)) {
result.add(new UnusedDescription(el, declaration,
isPkgPrivate, UnusedReason.NOT_WRITTEN));
} else if (!isRead) {
- if (isPrivate || isUnusedInPkg(info, el, cancel)) {
+ if ((isPrivate || isUnusedInPkg(info, el, cancel)) &&
!markedAsUsed.apply(el, declaration)) {
result.add(new UnusedDescription(el, declaration,
isPkgPrivate, UnusedReason.NOT_READ));
}
}
@@ -152,13 +168,13 @@ public class UnusedDetector {
if (!isSerializationMethod(info, method) &&
!uses.contains(UseTypes.USED)
&& !info.getElementUtilities().overridesMethod(method)
&& !lookedUpElement(el, uv.type2LookedUpMethods, uv.allStringLiterals)
&& !SourceUtils.isMainMethod(method)) {
- if (isPrivate || isUnusedInPkg(info, el, cancel)) {
+ if ((isPrivate || isUnusedInPkg(info, el, cancel)) &&
!markedAsUsed.apply(el, declaration)) {
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)) {
+ if ((isPrivate || isUnusedInPkg(info, el, cancel)) &&
!markedAsUsed.apply(el, declaration)) {
result.add(new UnusedDescription(el, declaration,
isPkgPrivate, UnusedReason.NOT_USED));
}
}
@@ -401,6 +417,17 @@ public class UnusedDetector {
return false;
}
+ private static List<UsedDetector> collectUsedDetectors(CompilationInfo
info) {
+ List<UsedDetector> detectors = new ArrayList<>();
+ for (UsedDetector.Factory factory :
Lookup.getDefault().lookupAll(UsedDetector.Factory.class)) {
+ UsedDetector detector = factory.create(info);
+ if (detector != null) {
+ detectors.add(detector);
+ }
+ }
+ return detectors;
+ }
+
private enum UseTypes {
READ, WRITTEN, USED;
}
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 34744e9678..e681ed7b97 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
@@ -21,7 +21,6 @@ package org.netbeans.modules.java.hints.bugs;
import com.sun.source.tree.Tree.Kind;
import java.util.ArrayList;
import java.util.List;
-import java.util.stream.Collectors;
import javax.lang.model.element.ElementKind;
import org.netbeans.modules.java.editor.base.semantic.UnusedDetector;
import
org.netbeans.modules.java.editor.base.semantic.UnusedDetector.UnusedDescription;
diff --git a/java/junit.ui/nbproject/project.xml
b/java/junit.ui/nbproject/project.xml
index aa582301ea..c3fc6fe537 100644
--- a/java/junit.ui/nbproject/project.xml
+++ b/java/junit.ui/nbproject/project.xml
@@ -207,6 +207,14 @@
<specification-version>1.78</specification-version>
</run-dependency>
</dependency>
+ <dependency>
+
<code-name-base>org.netbeans.spi.java.hints</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>1.56</specification-version>
+ </run-dependency>
+ </dependency>
<dependency>
<code-name-base>org.openide.awt</code-name-base>
<build-prerequisite/>
diff --git
a/java/junit.ui/src/org/netbeans/modules/junit/ui/actions/TestClassInfoTask.java
b/java/junit.ui/src/org/netbeans/modules/junit/ui/actions/TestClassInfoTask.java
index cf6ca19c42..051645ab73 100644
---
a/java/junit.ui/src/org/netbeans/modules/junit/ui/actions/TestClassInfoTask.java
+++
b/java/junit.ui/src/org/netbeans/modules/junit/ui/actions/TestClassInfoTask.java
@@ -25,7 +25,6 @@ import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
-import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
@@ -39,6 +38,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.swing.text.BadLocationException;
@@ -56,8 +56,8 @@ import
org.netbeans.modules.gsf.testrunner.ui.api.TestMethodController.TestMetho
import org.netbeans.modules.java.testrunner.ui.spi.ComputeTestMethods;
import org.netbeans.modules.java.testrunner.ui.spi.ComputeTestMethods.Factory;
import org.netbeans.modules.parsing.spi.Parser;
+import org.netbeans.spi.java.hints.unused.UsedDetector;
import org.netbeans.spi.project.SingleMethod;
-import org.openide.ErrorManager;
import org.openide.filesystems.FileObject;
import org.openide.util.Exceptions;
import org.openide.util.lookup.ServiceProvider;
@@ -255,6 +255,31 @@ public final class TestClassInfoTask implements
Task<CompilationController> {
}
}
+ @ServiceProvider(service=UsedDetector.Factory.class)
+ public static final class UsedDetectorImpl implements UsedDetector.Factory
{
+
+ @Override
+ public UsedDetector create(CompilationInfo info) {
+ if (isTestSource(info.getFileObject())) {
+ List<TestMethod> testMethods =
TestClassInfoTask.doComputeTestMethods(info, new AtomicBoolean(), -1);
+ SourcePositions sp = info.getTrees().getSourcePositions();
+ return (el, path) -> {
+ if (el.getKind() == ElementKind.METHOD) {
+ for (TestMethod tm : testMethods) {
+ if
(tm.method().getMethodName().contentEquals(el.getSimpleName())
+ && tm.start().getOffset() ==
sp.getStartPosition(path.getCompilationUnit(), path.getLeaf())
+ && tm.end().getOffset() ==
sp.getEndPosition(path.getCompilationUnit(), path.getLeaf())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+ }
+ return null;
+ }
+ }
+
@MimeRegistration(mimeType="text/x-java",
service=org.netbeans.modules.gsf.testrunner.ui.spi.ComputeTestMethods.class)
public static final class GenericComputeTestMethodsImpl implements
org.netbeans.modules.gsf.testrunner.ui.spi.ComputeTestMethods {
diff --git a/java/spi.java.hints/apichanges.xml
b/java/spi.java.hints/apichanges.xml
index d75974e8a5..54c6cb52e2 100644
--- a/java/spi.java.hints/apichanges.xml
+++ b/java/spi.java.hints/apichanges.xml
@@ -25,6 +25,23 @@
<apidef name="JavaHintsSPI">Java Hints SPI</apidef>
</apidefs>
<changes>
+ <change id="UsedDetector">
+ <api name="JavaHintsSPI"/>
+ <summary>Added UsedDetector SPI to mark an arbitrary elements as
used</summary>
+ <version major="1" minor="56"/>
+ <date day="2" month="8" year="2023"/>
+ <compatibility addition="yes"/>
+ <description>
+ <p>
+ The SPI to mark an arbitrary element as used was added.
+ Allows to suppress the standard NetBeans unused element
detection
+ and to prevent the "unused" hint being displayed on given
elements.
+ Can be used by various framework libraries that sometimes
honor
+ annotations (i.e. injections or bindings) even on private
methods.
+ </p>
+ </description>
+ <class package="org.netbeans.spi.java.hints.unused"
name="UsedDetector" link="no" />
+ </change>
<change id="openRefactoringUI">
<api name="JavaHintsSPI"/>
<summary>Added utility methods and SPI to open UI for
hints</summary>
diff --git a/java/spi.java.hints/nbproject/project.properties
b/java/spi.java.hints/nbproject/project.properties
index e8819b174c..e2e9fef7d2 100644
--- a/java/spi.java.hints/nbproject/project.properties
+++ b/java/spi.java.hints/nbproject/project.properties
@@ -17,7 +17,7 @@
is.autoload=true
javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial
-spec.version.base=1.55.0
+spec.version.base=1.56.0
requires.nb.javac=true
javadoc.arch=${basedir}/arch.xml
javadoc.apichanges=${basedir}/apichanges.xml
diff --git a/java/spi.java.hints/nbproject/project.xml
b/java/spi.java.hints/nbproject/project.xml
index d5a4f3fb8a..ac8c0a9c80 100644
--- a/java/spi.java.hints/nbproject/project.xml
+++ b/java/spi.java.hints/nbproject/project.xml
@@ -504,9 +504,8 @@
</test-dependencies>
<public-packages>
<package>org.netbeans.spi.java.hints</package>
- <package>org.netbeans.spi.java.hints.annotations</package>
- <package>org.netbeans.spi.java.hints.matching</package>
<package>org.netbeans.spi.java.hints.support</package>
+ <package>org.netbeans.spi.java.hints.unused</package>
</public-packages>
</data>
</configuration>
diff --git
a/java/spi.java.hints/src/org/netbeans/spi/java/hints/unused/UsedDetector.java
b/java/spi.java.hints/src/org/netbeans/spi/java/hints/unused/UsedDetector.java
new file mode 100644
index 0000000000..f0d74712b6
--- /dev/null
+++
b/java/spi.java.hints/src/org/netbeans/spi/java/hints/unused/UsedDetector.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.spi.java.hints.unused;
+
+import com.sun.source.util.TreePath;
+import javax.lang.model.element.Element;
+import org.netbeans.api.java.source.CompilationInfo;
+
+/**
+ * SPI to mark an arbitrary {@link Element} as used. Allows to suppress the
standard NetBeans
+ * unused element detection and to prevent the "unused" hint being displayed
on given elements.
+ * Can be used by various framework libraries that sometimes honor annotations
+ * (i.e. injections or bindings) even on private methods.
+ *
+ * @since 1.56
+ */
+public interface UsedDetector {
+
+ /**
+ * Checks whether given element should be marked as "used".
+ * @param el element to check
+ * @param path path to the element to check
+ * @return true if the given element should be marked as "used"
+ * @since 1.56
+ */
+ boolean isUsed(Element el, TreePath path);
+
+ /**
+ * Factory to create {@link UsedDetector} instances.
+ * @since 1.56
+ */
+ public interface Factory {
+ /**
+ * Creates {@link UsedDetector} instance for the given {@link
CompilationInfo}.
+ * @param info
+ * @return {@link UsedDetector} instance or null.
+ * @since 1.56
+ */
+ UsedDetector create(CompilationInfo info);
+ }
+}
---------------------------------------------------------------------
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