sdedic closed pull request #287: Fix 271823 False positive of "Non-null method 
returns null"
URL: https://github.com/apache/incubator-netbeans/pull/287
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/java.hints/src/org/netbeans/modules/java/hints/bugs/NPECheck.java 
b/java.hints/src/org/netbeans/modules/java/hints/bugs/NPECheck.java
index 4420fc09d..b7b5af852 100644
--- a/java.hints/src/org/netbeans/modules/java/hints/bugs/NPECheck.java
+++ b/java.hints/src/org/netbeans/modules/java/hints/bugs/NPECheck.java
@@ -190,6 +190,7 @@ public static ErrorDescription 
unboxingConditional(HintContext ctx) {
         if (np == null || !ci.getTypes().isAssignable(np, resType)) {
             return null;
         }
+        assert npPath != null;
 
         Map<Tree, State> expressionsState = computeExpressionsState(ctx);
         State s = expressionsState.get(npPath.getLeaf());
@@ -300,7 +301,7 @@ public static boolean isSafeToDereference(CompilationInfo 
info, TreePath path) {
     @TriggerTreeKind(Kind.METHOD_INVOCATION)
     public static List<ErrorDescription> methodInvocation(HintContext ctx) {
         MethodInvocationTree mit = (MethodInvocationTree) 
ctx.getPath().getLeaf();
-        List<State> paramStates = new 
ArrayList<State>(mit.getArguments().size());
+        List<State> paramStates = new ArrayList<>(mit.getArguments().size());
         Map<Tree, State> expressionsState = computeExpressionsState(ctx);
 
         for (Tree param : mit.getArguments()) {
@@ -316,7 +317,7 @@ public static boolean isSafeToDereference(CompilationInfo 
info, TreePath path) {
 
         ExecutableElement ee = (ExecutableElement) e;
         int index = 0;
-        List<ErrorDescription> result = new ArrayList<ErrorDescription>();
+        List<ErrorDescription> result = new ArrayList<>();
         List<? extends VariableElement> params = ee.getParameters();
 
         for (VariableElement param : params) {
@@ -427,19 +428,26 @@ public static ErrorDescription returnNull(HintContext 
ctx) {
 
         if (returnState == null) return null;
 
-        TreePath method = ctx.getPath();
+        TreePath method = Utilities.findOwningExecutable(ctx, ctx.getPath(), 
true);
+        if (method == null) return null;
 
-        while (method != null && method.getLeaf().getKind() != Kind.METHOD && 
method.getLeaf().getKind() != Kind.CLASS) {
-            method = method.getParentPath();
-        }
-
-        if (method == null || method.getLeaf().getKind() != Kind.METHOD) 
return null;
+        CompilationInfo info = ctx.getInfo();
 
-        Element el = ctx.getInfo().getTrees().getElement(method);
+        Element el = null;
+        switch (method.getLeaf().getKind()) {
+            case LAMBDA_EXPRESSION:
+                TypeMirror functionalType = 
info.getTrees().getTypeMirror(method);
+                if (!Utilities.isValidType(functionalType) || 
functionalType.getKind() != TypeKind.DECLARED) return null;
+                el = 
info.getElementUtilities().getDescriptorElement((TypeElement) ((DeclaredType) 
functionalType).asElement());
+                break;
+            case METHOD:
+                el = info.getTrees().getElement(method);
+                break;
+        }
 
         if (el == null || el.getKind() != ElementKind.METHOD) return null;
 
-        State expected = getStateFromAnnotations(ctx.getInfo(), el);
+        State expected = getStateFromAnnotations(info, el);
         String key = null;
 
         switch (returnState) {
@@ -472,9 +480,9 @@ public static ErrorDescription returnNull(HintContext ctx) {
         VisitorImpl v = new VisitorImpl(ctx, info, null);
         
         v.scan(info.getCompilationUnit(), null);
-        
-        info.putCachedValue(KEY_EXPRESSION_STATE, result = v.expressionState, 
CompilationInfo.CacheClearPolicy.ON_TASK_END);
-        
+
+        result = v.expressionState;
+        info.putCachedValue(KEY_EXPRESSION_STATE, result, 
CompilationInfo.CacheClearPolicy.ON_TASK_END);
         return result;
     }
     //Cancelling:
@@ -488,8 +496,9 @@ public static ErrorDescription returnNull(HintContext ctx) {
         VisitorImpl v = new VisitorImpl(ctx);
         
         v.scan(ctx.getInfo().getCompilationUnit(), null);
-        
-        ctx.getInfo().putCachedValue(KEY_EXPRESSION_STATE, result = 
v.expressionState, CompilationInfo.CacheClearPolicy.ON_TASK_END);
+
+        result = v.expressionState;
+        ctx.getInfo().putCachedValue(KEY_EXPRESSION_STATE, result, 
CompilationInfo.CacheClearPolicy.ON_TASK_END);
         return result;
     }
     
@@ -539,18 +548,18 @@ private static State 
getStateFromAnnotations(CompilationInfo info, Element e, St
          * Tracks variables which are in scope. When a variable goes out of 
scope, its state (if any) moves
          * to {@link #variable2StateFinal}.
          */
-        private Map<VariableElement, State> variable2State = new 
HashMap<VariableElement, State>();
+        private Map<VariableElement, State> variable2State = new HashMap<>();
 
         /**
          * Finalized state of variables. Records for variables, which go out 
of scope is collected here.
          */
-        private Map<VariableElement, State> variable2StateFinal = new 
HashMap<VariableElement, State>();
+        private final Map<VariableElement, State> variable2StateFinal = new 
HashMap<>();
         
-        private final Map<Tree, Collection<Map<VariableElement, State>>> 
resumeBefore = new IdentityHashMap<Tree, Collection<Map<VariableElement, 
State>>>();
-        private final Map<Tree, Collection<Map<VariableElement, State>>> 
resumeAfter = new IdentityHashMap<Tree, Collection<Map<VariableElement, 
State>>>();
-        private       Map<TypeMirror, Map<VariableElement, State>> 
resumeOnExceptionHandler = new IdentityHashMap<TypeMirror, Map<VariableElement, 
State>>();
-        private final Map<Tree, State> expressionState = new 
IdentityHashMap<Tree, State>();
-        private final List<TreePath> pendingFinally = new 
LinkedList<TreePath>();
+        private final Map<Tree, Collection<Map<VariableElement, State>>> 
resumeBefore = new IdentityHashMap<>();
+        private final Map<Tree, Collection<Map<VariableElement, State>>> 
resumeAfter = new IdentityHashMap<>();
+        private       Map<TypeMirror, Map<VariableElement, State>> 
resumeOnExceptionHandler = new IdentityHashMap<>();
+        private final Map<Tree, State> expressionState = new 
IdentityHashMap<>();
+        private final List<TreePath> pendingFinally = new LinkedList<>();
         private boolean not;
         private boolean doNotRecord;
         private final TypeElement throwableEl;
@@ -562,7 +571,7 @@ private static State 
getStateFromAnnotations(CompilationInfo info, Element e, St
          * when the traversal exits the tree, to clean up variables that go 
out of scope from
          * variable2State, so state cloning takes less memory
          */
-        private final Map<Tree, Collection<VariableElement>> scopedVariables = 
new IdentityHashMap<Tree, Collection<VariableElement>>();
+        private final Map<Tree, Collection<VariableElement>> scopedVariables = 
new IdentityHashMap<>();
                 
         public VisitorImpl(HintContext ctx, CompilationInfo aInfo, 
AtomicBoolean cancel) {
             this.ctx = ctx;
@@ -649,7 +658,7 @@ private void resume(Tree tree, Map<Tree, 
Collection<Map<VariableElement, State>>
         @Override
         public State visitAssignment(AssignmentTree node, Void p) {
             Element e = info.getTrees().getElement(new 
TreePath(getCurrentPath(), node.getVariable()));
-            Map<VariableElement, State> orig = new HashMap<VariableElement, 
State>(variable2State);
+            Map<VariableElement, State> orig = new HashMap<>(variable2State);
             State r = scan(node.getExpression(), p);
             
             scan(node.getVariable(), p);
@@ -665,7 +674,7 @@ public State visitAssignment(AssignmentTree node, Void p) {
 
         @Override
         public State visitCompoundAssignment(CompoundAssignmentTree node, Void 
p) {
-            Map<VariableElement, State> orig = new HashMap<VariableElement, 
State>(variable2State);
+            Map<VariableElement, State> orig = new HashMap<>(variable2State);
             
             scan(node.getExpression(), p);
             scan(node.getVariable(), p);
@@ -678,7 +687,7 @@ public State visitCompoundAssignment(CompoundAssignmentTree 
node, Void p) {
         private void addScopedVariable(Tree t, VariableElement ve) {
             Collection<VariableElement> c = scopedVariables.get(t);
             if (c == null) {
-                c = new ArrayList<VariableElement>(3);
+                c = new ArrayList<>(3);
                 scopedVariables.put(t, c);
             }
             c.add(ve);
@@ -687,7 +696,7 @@ private void addScopedVariable(Tree t, VariableElement ve) {
         @Override
         public State visitVariable(VariableTree node, Void p) {
             Element e = info.getTrees().getElement(getCurrentPath());
-            Map<VariableElement, State> orig = new HashMap<VariableElement, 
State>(variable2State);
+            Map<VariableElement, State> orig = new HashMap<>(variable2State);
             State r = scan(node.getInitializer(), p);
             
             mergeHypotheticalVariable2State(orig);
@@ -714,7 +723,7 @@ public State visitMemberSelect(MemberSelectTree node, Void 
p) {
             
             Element site = info.getTrees().getElement(new 
TreePath(getCurrentPath(), node.getExpression()));
             
-            if (isVariableElement(site) && wasNPE && (variable2State.get(site) 
== null || !variable2State.get(site).isNotNull())) {
+            if (isVariableElement(site) && wasNPE && 
(variable2State.get((VariableElement) site) == null || 
!variable2State.get((VariableElement) site).isNotNull())) {
                 variable2State.put((VariableElement) site, NOT_NULL_BE_NPE);
             }
             // special case: if the memberSelect selects enum field = 
constant, it is never null.
@@ -739,15 +748,15 @@ public State visitLiteral(LiteralTree node, Void p) {
 
         @Override
         public State visitIf(IfTree node, Void p) {
-            Map<VariableElement, State> oldVariable2StateBeforeCondition = new 
HashMap<VariableElement, State>(variable2State);
+            Map<VariableElement, State> oldVariable2StateBeforeCondition = new 
HashMap<>(variable2State);
             
             State condition = scan(node.getCondition(), p);
             
             scan(node.getThenStatement(), null);
             
-            Map<VariableElement, State> variableStatesAfterThen = new 
HashMap<VariableElement, NPECheck.State>(variable2State);
+            Map<VariableElement, State> variableStatesAfterThen = new 
HashMap<>(variable2State);
             
-            variable2State = new HashMap<VariableElement, 
NPECheck.State>(oldVariable2StateBeforeCondition);
+            variable2State = new HashMap<>(oldVariable2StateBeforeCondition);
             not = true;
             doNotRecord = true;
             scan(node.getCondition(), p);
@@ -794,7 +803,7 @@ public State visitBinary(BinaryTree node, Void p) {
                     break;
 
                 case CONDITIONAL_OR: {
-                    HashMap<VariableElement, State> orig = new 
HashMap<VariableElement, NPECheck.State>(variable2State);
+                    HashMap<VariableElement, State> orig = new 
HashMap<>(variable2State);
 
                     scan(node.getLeftOperand(), p);
 
@@ -830,7 +839,7 @@ public State visitBinary(BinaryTree node, Void p) {
                 if (right == State.NULL) {
                     Element e = info.getTrees().getElement(new 
TreePath(getCurrentPath(), node.getLeftOperand()));
                     
-                    if (isVariableElement(e) && !hasDefiniteValue(e)) {
+                    if (isVariableElement(e) && 
!hasDefiniteValue((VariableElement) e)) {
                         variable2State.put((VariableElement) e, 
State.NULL_HYPOTHETICAL);
                         
                         return null;
@@ -839,7 +848,7 @@ public State visitBinary(BinaryTree node, Void p) {
                 if (left == State.NULL) {
                     Element e = info.getTrees().getElement(new 
TreePath(getCurrentPath(), node.getRightOperand()));
                     
-                    if (isVariableElement(e) && !hasDefiniteValue(e)) {
+                    if (isVariableElement(e) && 
!hasDefiniteValue((VariableElement) e)) {
                         variable2State.put((VariableElement) e, 
State.NULL_HYPOTHETICAL);
                         
                         return null;
@@ -851,7 +860,7 @@ public State visitBinary(BinaryTree node, Void p) {
                 if (right == State.NULL) {
                     Element e = info.getTrees().getElement(new 
TreePath(getCurrentPath(), node.getLeftOperand()));
                     
-                    if (isVariableElement(e) && !hasDefiniteValue(e)) {
+                    if (isVariableElement(e) && 
!hasDefiniteValue((VariableElement) e)) {
                         variable2State.put((VariableElement) e, 
State.NOT_NULL_HYPOTHETICAL);
                         
                         return null;
@@ -860,7 +869,7 @@ public State visitBinary(BinaryTree node, Void p) {
                 if (left == State.NULL) {
                     Element e = info.getTrees().getElement(new 
TreePath(getCurrentPath(), node.getRightOperand()));
                     
-                    if (isVariableElement(e) && !hasDefiniteValue(e)) {
+                    if (isVariableElement(e) && 
!hasDefiniteValue((VariableElement) e)) {
                         variable2State.put((VariableElement) e, 
State.NOT_NULL_HYPOTHETICAL);
                         
                         return null;
@@ -877,7 +886,7 @@ public State visitInstanceOf(InstanceOfTree node, Void p) {
             
             Element e = info.getTrees().getElement(new 
TreePath(getCurrentPath(), node.getExpression()));
 
-            if (isVariableElement(e) && (variable2State.get(e) == null || 
!variable2State.get(e).isNotNull()) && !not) {
+            if (isVariableElement(e) && (variable2State.get((VariableElement) 
e) == null || !variable2State.get((VariableElement) e).isNotNull()) && !not) {
                 variable2State.put((VariableElement) e, 
State.NOT_NULL_HYPOTHETICAL);
             }
             
@@ -887,7 +896,7 @@ public State visitInstanceOf(InstanceOfTree node, Void p) {
         @Override
         public State visitConditionalExpression(ConditionalExpressionTree 
node, Void p) {
             //TODO: handle the condition similarly to visitIf
-            Map<VariableElement, State> oldVariable2State = new 
HashMap<VariableElement, State>(variable2State);
+            Map<VariableElement, State> oldVariable2State = new 
HashMap<>(variable2State);
             
             scan(node.getCondition(), p);
             
@@ -920,7 +929,7 @@ public State visitNewClass(NewClassTree node, Void p) {
             
             for (Tree param : node.getArguments()) {
                 Map<VariableElement, State> origVariable2State = 
variable2State;
-                variable2State = new HashMap<VariableElement, 
State>(variable2State);
+                variable2State = new HashMap<>(variable2State);
                 scan(param, p);
                 mergeNonHypotheticalVariable2State(origVariable2State);
             }
@@ -943,7 +952,7 @@ public State visitMethodInvocation(MethodInvocationTree 
node, Void p) {
             
             for (Tree param : node.getArguments()) {
                 Map<VariableElement, State> origVariable2State = 
variable2State;
-                variable2State = new HashMap<VariableElement, 
State>(variable2State);
+                variable2State = new HashMap<>(variable2State);
                 scan(param, p);
                 mergeNonHypotheticalVariable2State(origVariable2State);
             }
@@ -1044,13 +1053,10 @@ public State visitIdentifier(IdentifierTree node, Void 
p) {
                 // enum constants are never null
                 return State.NOT_NULL;
             }
-            
-            if (e != null) {
-                State s = variable2State.get(e);
-                
-                if (s != null) {
-                    return s;
-                }
+
+            State s = variable2State.get((VariableElement) e);
+            if (s != null) {
+                return s;
             }
             
             return getStateFromAnnotations(info, e);
@@ -1086,7 +1092,7 @@ public State visitMethod(MethodTree node, Void p) {
             resumeOnExceptionHandler = new IdentityHashMap<>();
             
             try {
-                variable2State = new HashMap<VariableElement, 
NPECheck.State>();
+                variable2State = new HashMap<>();
                 not = false;
 
                 Element current = info.getTrees().getElement(getCurrentPath());
@@ -1127,7 +1133,7 @@ public State visitEnhancedForLoop(EnhancedForLoopTree 
node, Void p) {
         private boolean inCycle = false;
         
         private Map<VariableElement, State> 
findStateDifference(Map<VariableElement, State> basepoint) {
-            Map<VariableElement, State> m = new HashMap<VariableElement, 
State>();
+            Map<VariableElement, State> m = new HashMap<>();
             for (Map.Entry<VariableElement, State> vEntry : 
variable2State.entrySet()) {
                 VariableElement k = vEntry.getKey();
                 State s = basepoint.get(k);
@@ -1141,7 +1147,7 @@ public State visitEnhancedForLoop(EnhancedForLoopTree 
node, Void p) {
         private State handleGeneralizedFor(Iterable<? extends Tree> 
initializer, Tree condition, Iterable<? extends Tree> update, Tree statement, 
Void p) {
             scan(initializer, p);
             
-            Map<VariableElement, State> oldVariable2State = new 
HashMap<VariableElement, State>(variable2State);
+            Map<VariableElement, State> oldVariable2State = new 
HashMap<>(variable2State);
 
             boolean oldNot = not;
             boolean oldDoNotRecord = doNotRecord;
@@ -1153,7 +1159,7 @@ private State handleGeneralizedFor(Iterable<? extends 
Tree> initializer, Tree co
             
             not = oldNot;
             
-              Map<VariableElement, State> negConditionVariable2State = new 
HashMap<VariableElement, State>(variable2State);
+              Map<VariableElement, State> negConditionVariable2State = new 
HashMap<>(variable2State);
             // get just the _changed_ stuff
             Map<VariableElement, State> negConditionChanges2State = 
findStateDifference(oldVariable2State);
             
@@ -1162,7 +1168,7 @@ private State handleGeneralizedFor(Iterable<? extends 
Tree> initializer, Tree co
             
             if (!inCycle) {
                 inCycle = true;
-                variable2State = new HashMap<VariableElement, 
State>(oldVariable2State);
+                variable2State = new HashMap<>(oldVariable2State);
                 
                 scan(condition, p);
                 scan(statement, p);
@@ -1197,11 +1203,12 @@ public State visitArrayAccess(ArrayAccessTree node, 
Void p) {
             super.visitArrayAccess(node, p);
             return State.POSSIBLE_NULL;
         }
-        
+
+        @Override
         public State visitSwitch(SwitchTree node, Void p) {
             scan(node.getExpression(), null);
 
-            Map<VariableElement, State> origVariable2State = new 
HashMap<VariableElement, State>(variable2State);
+            Map<VariableElement, State> origVariable2State = new 
HashMap<>(variable2State);
 
             boolean exhaustive = false;
 
@@ -1221,7 +1228,8 @@ public State visitSwitch(SwitchTree node, Void p) {
             
             return null;
         }
-        
+
+        @Override
         public State visitBreak(BreakTree node, Void p) {
             super.visitBreak(node, p);
 
@@ -1229,11 +1237,12 @@ public State visitBreak(BreakTree node, Void p) {
             
             resumeAfter(target, variable2State);
 
-            variable2State = new HashMap<VariableElement, State>(); //XXX: 
fields?
+            variable2State = new HashMap<>(); //XXX: fields?
             
             return null;
         }
-        
+
+        @Override
         public State visitTry(TryTree node, Void p) {
             Map<TypeMirror, Map<VariableElement, State>> 
oldResumeOnExceptionHandler = resumeOnExceptionHandler;
 
@@ -1248,7 +1257,7 @@ public State visitTry(TryTree node, Void p) {
 
             Map<VariableElement, State> oldVariable2State = variable2State;
 
-            variable2State = new HashMap<VariableElement, 
State>(oldVariable2State);
+            variable2State = new HashMap<>(oldVariable2State);
 
             // resumeOnEx will save states from potential exceptions thrown by 
try siblings
             // or outer blocks. 
@@ -1256,15 +1265,15 @@ public State visitTry(TryTree node, Void p) {
             Map<TypeMirror, Map<VariableElement, State>> resumeOnEx = null;
             List<TypeMirror> caughtTypes = null;
             if (node.getCatches() != null && !node.getCatches().isEmpty()) {
-                caughtTypes = new 
ArrayList<TypeMirror>(node.getCatches().size());
-                resumeOnEx = new IdentityHashMap<TypeMirror, 
Map<VariableElement, State>>(caughtTypes.size());
+                caughtTypes = new ArrayList<>(node.getCatches().size());
+                resumeOnEx = new IdentityHashMap<>(caughtTypes.size());
                 for (CatchTree ct : node.getCatches()) {
                     for (TypeMirror exT : Utilities.getUnionExceptions(info, 
getCurrentPath(), ct)) {
                         Map<VariableElement, State> data = 
resumeOnExceptionHandler.get(exT);
                         if (data != null) {
                             resumeOnEx.put(exT, data);
                         }
-                        resumeOnExceptionHandler.put(exT, new 
HashMap<VariableElement, State>());
+                        resumeOnExceptionHandler.put(exT, new HashMap<>());
                         caughtTypes.add(exT);
                     }
                 }
@@ -1280,11 +1289,12 @@ public State visitTry(TryTree node, Void p) {
                 recordResumeOnExceptionHandler(runtimeExceptionType);
                 recordResumeOnExceptionHandler(errorType);
             }
-            HashMap<VariableElement, State> afterBlockVariable2State = new 
HashMap<VariableElement, State>(variable2State);
+            HashMap<VariableElement, State> afterBlockVariable2State = new 
HashMap<>(variable2State);
 
             // catch handlers and finally block will report exception to outer 
catches, restore
             // masked exception types
             if (caughtTypes != null) {
+                assert resumeOnEx != null;
                 for (TypeMirror exT : caughtTypes) {
                     Map<VariableElement, State> oldData = 
resumeOnEx.remove(exT);
                     Map<VariableElement, State> data = 
resumeOnExceptionHandler.remove(exT);
@@ -1295,26 +1305,27 @@ public State visitTry(TryTree node, Void p) {
                         resumeOnExceptionHandler.put(exT, oldData);
                     }
                 }
-            }
 
-            for (CatchTree ct : node.getCatches()) {
-                Map<VariableElement, State> variable2StateBeforeCatch = 
variable2State;
+                assert node.getCatches() != null;
+                for (CatchTree ct : node.getCatches()) {
+                    Map<VariableElement, State> variable2StateBeforeCatch = 
variable2State;
 
-                variable2State = new HashMap<VariableElement, 
State>(oldVariable2State);
+                    variable2State = new HashMap<>(oldVariable2State);
 
-                for (TypeMirror cc : Utilities.getUnionExceptions(info, 
getCurrentPath(), ct)) {
-                    Map<VariableElement, State> data = resumeOnEx.get(cc);
-                    if (data != null) {
-                        mergeIntoVariable2State(data);
+                    for (TypeMirror cc : Utilities.getUnionExceptions(info, 
getCurrentPath(), ct)) {
+                        Map<VariableElement, State> data = resumeOnEx.get(cc);
+                        if (data != null) {
+                            mergeIntoVariable2State(data);
+                        }
                     }
-                }
-                
-                scan(ct, null);
 
-                if (Utilities.exitsFromAllBranchers(info, new 
TreePath(getCurrentPath(), ct))) {
-                    variable2State = variable2StateBeforeCatch;
-                } else {
-                    mergeIntoVariable2State(variable2StateBeforeCatch);
+                    scan(ct, null);
+
+                    if (Utilities.exitsFromAllBranchers(info, new 
TreePath(getCurrentPath(), ct))) {
+                        variable2State = variable2StateBeforeCatch;
+                    } else {
+                        mergeIntoVariable2State(variable2StateBeforeCatch);
+                    }
                 }
             }
 
@@ -1412,10 +1423,11 @@ private static void recordResume(Map<Tree, 
Collection<Map<VariableElement, State
             Collection<Map<VariableElement, State>> r = resume.get(target);
 
             if (r == null) {
-                resume.put(target, r = new ArrayList<Map<VariableElement, 
State>>());
+                r = new ArrayList<>();
+                resume.put(target, r);
             }
 
-            r.add(new HashMap<VariableElement, State>(state));
+            r.add(new HashMap<>(state));
         }
         
         private void forceIntoVariable2State(Map<VariableElement, State> 
other) {
@@ -1473,7 +1485,7 @@ private void 
mergeNonHypotheticalVariable2State(Map<VariableElement, State> orig
             }
         }
         
-        private boolean hasDefiniteValue(Element el) {
+        private boolean hasDefiniteValue(VariableElement el) {
             State s = variable2State.get(el);
             
             return s != null && s.isNotNull();
diff --git 
a/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/NPECheckTest.java
 
b/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/NPECheckTest.java
index ebd61d50b..185f9e3ae 100644
--- 
a/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/NPECheckTest.java
+++ 
b/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/NPECheckTest.java
@@ -19,7 +19,6 @@
 
 package org.netbeans.modules.java.hints.bugs;
 
-import junit.framework.TestSuite;
 import org.netbeans.junit.NbTestCase;
 import org.netbeans.modules.java.hints.test.api.HintTest;
 import org.openide.filesystems.FileUtil;
@@ -1615,6 +1614,37 @@ public void 
testUnboxingInTernaryPossibleNullWorksWithOption() throws Exception
                 );
     }
 
+    public void testLambdaExpressionShouldntReturnNull() throws Exception {
+        HintTest.create()
+                .sourceLevel("8")
+                .input("package test;\n" +
+                        "\n" +
+                        "import java.util.function.Function;\n" +
+                        "\n" +
+                        "public class Test {\n" +
+                        "\n" +
+                        "    interface Custom {\n" +
+                        "        @Nonnull\n" +
+                        "        Object doStuff();\n" +
+                        "    }\n" +
+                        "\n" +
+                        "    @Nonnull\n" +
+                        "    public static Object test() {\n" +
+                        "        Function<String, String> f = (input) -> {\n" +
+                        "            return null;\n" + // shouldn't warn 
(#271823)
+                        "        };\n" +
+                        "        Object o = (Custom) (() -> {\n" +
+                        "            return null;\n" +
+                        "        });\n" +
+                        "        return new Object();\n" +
+                        "    }\n" +
+                        "\n" +
+                        "    @interface Nonnull { }\n" +
+                        "}")
+                .run(NPECheck.class)
+                
.assertWarnings("17:19-17:23:verifier:ERR_ReturningNullFromNonNull");
+    }
+
     private void performAnalysisTest(String fileName, String code, String... 
golden) throws Exception {
         HintTest.create()
                 .input(fileName, code)


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to