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 <mbie...@gmail.com>
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: commits-unsubscr...@netbeans.apache.org
For additional commands, e-mail: commits-h...@netbeans.apache.org

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

Reply via email to