This is an automated email from the ASF dual-hosted git repository.
mbien 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 b2e0288af6 ConvertToLambda hint should ignore default methods.
new 3e5661f4b3 Merge pull request #6658 from
mbien/no-lambda-for-default-methods
b2e0288af6 is described below
commit b2e0288af62653fc59b94cbd336422af30be87b7
Author: Michael Bien <[email protected]>
AuthorDate: Fri Nov 3 05:55:53 2023 +0100
ConvertToLambda hint should ignore default methods.
Default methods don't qualify for functional interfaces since they
are not abstract and can therefore not be converted into lambdas.
---
.../modules/java/hints/jdk/ConvertToLambda.java | 5 +-
.../java/hints/jdk/ConvertToLambdaConverter.java | 3 -
.../jdk/ConvertToLambdaPreconditionChecker.java | 33 ++++++++++-
.../java/hints/jdk/ConvertToLambdaTest.java | 64 ++++++++++++++++++++++
4 files changed, 96 insertions(+), 9 deletions(-)
diff --git
a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToLambda.java
b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToLambda.java
index 38244c446c..6c134a95af 100644
---
a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToLambda.java
+++
b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToLambda.java
@@ -21,7 +21,6 @@
*/
package org.netbeans.modules.java.hints.jdk;
-import com.sun.source.tree.ClassTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.Tree.Kind;
import com.sun.source.util.TreePath;
@@ -29,7 +28,6 @@ import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
-import javax.tools.Diagnostic;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.JavaSource.Phase;
import org.netbeans.api.java.source.WorkingCopy;
@@ -56,7 +54,7 @@ import org.openide.util.NbBundle;
public class ConvertToLambda {
public static final String ID = "Javac_canUseLambda"; //NOI18N
- public static final Set<String> CODES = new
HashSet<String>(Arrays.asList("compiler.warn.potential.lambda.found")); //NOI18N
+ public static final Set<String> CODES = new
HashSet<>(Arrays.asList("compiler.warn.potential.lambda.found")); //NOI18N
static final boolean DEF_PREFER_MEMBER_REFERENCES = true;
@@ -68,7 +66,6 @@ public class ConvertToLambda {
})
@NbBundle.Messages("MSG_AnonymousConvertibleToLambda=This anonymous inner
class creation can be turned into a lambda expression.")
public static ErrorDescription computeAnnonymousToLambda(HintContext ctx) {
- ClassTree clazz = ((NewClassTree)
ctx.getPath().getLeaf()).getClassBody();
ConvertToLambdaPreconditionChecker preconditionChecker =
new ConvertToLambdaPreconditionChecker(ctx.getPath(),
ctx.getInfo());
if (!preconditionChecker.passesFatalPreconditions()) {
diff --git
a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToLambdaConverter.java
b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToLambdaConverter.java
index ee53aca15c..963ae107fc 100644
---
a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToLambdaConverter.java
+++
b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToLambdaConverter.java
@@ -21,7 +21,6 @@
*/
package org.netbeans.modules.java.hints.jdk;
-import com.sun.source.tree.BlockTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.ExpressionTree;
import com.sun.source.tree.IdentifierTree;
@@ -48,9 +47,7 @@ import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.ReturnTree;
import java.util.List;
-import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
-import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.TreeMaker;
import org.netbeans.api.java.source.WorkingCopy;
import org.netbeans.api.java.source.matching.Matcher;
diff --git
a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToLambdaPreconditionChecker.java
b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToLambdaPreconditionChecker.java
index b13179430c..08abae6e15 100644
---
a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToLambdaPreconditionChecker.java
+++
b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToLambdaPreconditionChecker.java
@@ -50,6 +50,8 @@ import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.ElementFilter;
+import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import org.netbeans.api.java.source.CompilationInfo;
import org.netbeans.api.java.source.TreeUtilities;
@@ -64,6 +66,7 @@ public class ConvertToLambdaPreconditionChecker {
private final Scope localScope;
private final CompilationInfo info;
private final Types types;
+ private final Elements elements;
private boolean foundRefToThisOrSuper = false;
private boolean foundShadowedVariable = false;
private boolean foundRecursiveCall = false;
@@ -85,6 +88,7 @@ public class ConvertToLambdaPreconditionChecker {
this.newClassTree = (NewClassTree) pathToNewClassTree.getLeaf();
this.info = info;
this.types = info.getTypes();
+ this.elements = info.getElements();
Element el = info.getTrees().getElement(pathToNewClassTree);
if (el != null && el.getKind() == ElementKind.CONSTRUCTOR) {
@@ -137,7 +141,32 @@ public class ConvertToLambdaPreconditionChecker {
candidate = (MethodTree)member;
}
}
- return candidate;
+ // only abstract methods can be implemented as lambda (e.g default
methods can't)
+ ExecutableElement candidateElement = (ExecutableElement)
info.getTrees().getElement(new TreePath(pathToNewClassTree, candidate));
+ if (overridesAbstractMethod(candidateElement, (TypeElement)
baseElement)) {
+ return candidate;
+ }
+ return null;
+ }
+
+ private boolean overridesAbstractMethod(ExecutableElement method,
TypeElement superType) {
+ Boolean overrides = overridesAbstractMethodImpl(method, superType);
+ return overrides != null && overrides;
+ }
+
+ private Boolean overridesAbstractMethodImpl(ExecutableElement method,
TypeElement superType) {
+ for (ExecutableElement otherMethod :
ElementFilter.methodsIn(superType.getEnclosedElements())) {
+ if (elements.overrides(method, otherMethod, superType)) {
+ return otherMethod.getModifiers().contains(Modifier.ABSTRACT);
+ }
+ }
+ for (TypeMirror otherType : superType.getInterfaces()) {
+ Boolean overrides = overridesAbstractMethodImpl(method,
(TypeElement) types.asElement(otherType));
+ if (overrides != null) {
+ return overrides;
+ }
+ }
+ return null; // no match here but check the rest of the interface tree
}
public boolean passesAllPreconditions() {
@@ -716,7 +745,7 @@ public class ConvertToLambdaPreconditionChecker {
}
private List<TypeMirror> getTypesFromElements(List<? extends
VariableElement> elements) {
- List<TypeMirror> elementTypes = new ArrayList<TypeMirror>();
+ List<TypeMirror> elementTypes = new ArrayList<>(elements.size());
for (Element e : elements) {
elementTypes.add(e.asType());
}
diff --git
a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertToLambdaTest.java
b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertToLambdaTest.java
index 3574930aeb..50e21cb05c 100644
---
a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertToLambdaTest.java
+++
b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertToLambdaTest.java
@@ -1101,6 +1101,70 @@ public class ConvertToLambdaTest extends NbTestCase {
}
+ // default methods don't qualify for functional interfaces
+ public void testThatDefaultMethodsAreIgnored1() throws Exception {
+ HintTest.create()
+ .sourceLevel("1.8")
+ .input("package test;\n" +
+ "public class Test {\n" +
+ " private interface NotFunctional {\n" +
+ " public default void a(int i) {};\n" +
+ " }\n" +
+ " NotFunctional nf = new NotFunctional() {\n" +
+ " @Override public void a(int i) {
System.err.println(i); }\n" +
+ " };\n" +
+ "}\n")
+ .run(ConvertToLambda.class)
+ .assertWarnings();
+ }
+
+ public void testThatDefaultMethodsAreIgnored2() throws Exception {
+ HintTest.create()
+ .sourceLevel("1.8")
+ .input("package test;\n" +
+ "public class Test {\n" +
+ " private interface DefaultRunnableNotFunctional1
extends Runnable {\n" +
+ " @Override public default void run() {};\n" +
+ " }\n" +
+ " private interface DefaultRunnableNotFunctional2
extends DefaultRunnableNotFunctional1 {}\n" +
+ " DefaultRunnableNotFunctional2 nf = new
DefaultRunnableNotFunctional2() {\n" +
+ " @Override public void run() {
System.err.println(); }\n" +
+ " };\n" +
+ "}\n")
+ .run(ConvertToLambda.class)
+ .assertWarnings();
+ }
+
+ public void testThatDefaultMethodsAreIgnored3() throws Exception {
+ HintTest.create()
+ .sourceLevel("1.8")
+ .input("package test;\n" +
+ "public class Test {\n" +
+ " private interface DefaultRunnableFunctional1
extends Runnable {\n" +
+ " public void walk();\n" +
+ " @Override public default void run() {};\n" +
+ " }\n" +
+ " private interface DefaultRunnableFunctional2
extends DefaultRunnableFunctional1 {}\n" +
+ " DefaultRunnableFunctional2 f = new
DefaultRunnableFunctional2() {\n" +
+ " @Override public void walk() {
System.err.println(5); }\n" +
+ " };\n" +
+ "}\n")
+ .run(ConvertToLambda.class)
+ .findWarning("7:39-7:65:" + lambdaConvWarning)
+ .applyFix()
+ .assertOutput("package test;\n" +
+ "public class Test {\n" +
+ " private interface DefaultRunnableFunctional1
extends Runnable {\n" +
+ " public void walk();\n" +
+ " @Override public default void run() {};\n" +
+ " }\n" +
+ " private interface DefaultRunnableFunctional2
extends DefaultRunnableFunctional1 {}\n" +
+ " DefaultRunnableFunctional2 f = () -> {\n" +
+ " System.err.println(5);\n" +
+ " };\n" +
+ "}\n");
+ }
+
static {
TestCompilerSettings.commandLine = "-XDfind=lambda";
JavacParser.DISABLE_SOURCE_LEVEL_DOWNGRADE = true;
---------------------------------------------------------------------
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