Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 543617

Summary: [completion] Null expectedType when resolving completions in lambda expressions.
Product: [Eclipse Project] JDT Reporter: Gayan Perera <gayanper>
Component: CoreAssignee: Stephan Herrmann <stephan.herrmann>
Status: VERIFIED FIXED QA Contact:
Severity: major    
Priority: P3 CC: jarthana, stephan.herrmann
Version: 4.10   
Target Milestone: 4.20 M3   
Hardware: All   
OS: All   
See Also: https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/179696
https://bugs.eclipse.org/bugs/show_bug.cgi?id=539685
https://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=e6acd78ea2da8f35048b3bd85a7c2ce8c808f047
Whiteboard:

Description Gayan Perera CLA 2019-01-20 05:10:42 EST
When trying to invoke completions in the following code

package test.module;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class TestApp {
	private <E> void print(Iterator<E> iterator) {
                // doesn't shows chain proposals
		iterator.forEachRemaining(e -> load(|C1)); 

		this.load(|C2); 
	}

	public List<String> findAll() {
		return load(Collections.EMPTY_LIST);
	}

	public List<String> load(List<Long> ids) {
		return null;
	}
}

When invoking context assist in C2 cursor position, i received expectedType inside the context of IJavaCompletionProposalComputer implementation. But if i do the same in cursor position C1 the expectedType is null. This cause the Chain proposals not to work according to https://bugs.eclipse.org/bugs/show_bug.cgi?id=528380.

Further digging in i found out that in C2 position i receive a CompletionOnMessageSend instance as the CompletionNodeFound.astNode. But is C1 position i receive a CompletionOnSingleNameReference as the CompletionNodeFound.astNode, and this cause the expectedType resolution not to happen.
Comment 1 Stephan Herrmann CLA 2019-01-20 05:27:30 EST
(In reply to Gayan Perera from comment #0)
> Further digging in i found out that in C2 position i receive a
> CompletionOnMessageSend instance as the CompletionNodeFound.astNode.

Can you say more about this CompletionOnMessageSend? What is its selector: 'load', or 'C1' or s.t. completely different?

Note, that normally, it is "impossible" to resolve the expected type in a position like this, because inference of the entire line requires all details to be resolvable, and an unresolved 'C1' deep inside can mean that inference will fail altogether.

In this particular case, though, load(..) should be resolvable without much context information, since the implicit receiver does not depend on any inference results, and no overloading is involved.

Still, completion inside an incomplete lambda expression is a *very* fragile issue, so please don't hold your breath waiting for this to be fixed.
Comment 2 Gayan Perera CLA 2019-01-20 05:42:14 EST
@Stephan here |CI and |C2 are kind of none java code things i added to point to the cursor position in my explanation. So they are not part of the code. the code just looks like as below

public class TestApp {
	private <E> void print(Iterator<E> iterator) {
                // doesn't shows chain proposals
		iterator.forEachRemaining(e -> load(|)); 

		this.load(|); 
	}

	public List<String> findAll() {
		return load(Collections.EMPTY_LIST);
	}

	public List<String> load(List<Long> ids) {
		return null;
	}
}

Where the | char represents the cursor.
Comment 3 Gayan Perera CLA 2019-01-20 05:46:57 EST
When i'm on this.load(|) the e.astNode selector is 

<CompleteOnMessageSend:print()>

When i'm on iterator.forEachRemaining(e -> load(|)); the e.astNode selector is 

<CompleteOnName:>
Comment 4 Stephan Herrmann CLA 2019-01-20 07:12:11 EST
Now I'm confused :)

(In reply to Gayan Perera from comment #3)
> When i'm on this.load(|) the e.astNode selector is 
> 
> <CompleteOnMessageSend:print()>

That would mean we are not completing an argument to load() but the outermost message send itself, as if curser position would be:

   this.print|(something);
 
> When i'm on iterator.forEachRemaining(e -> load(|)); the e.astNode selector
> is 
> 
> <CompleteOnName:>

This could represent the (empty) name in argument position.

I would expect <CompleteOnName:> to work but <CompleteOnMessageSend:print()> to fail. Perhaps you swapped locations vs. results?
Comment 5 Gayan Perera CLA 2019-01-20 07:53:28 EST
@Stephan Nope i doubled checked.

Well the JDT suggestions are their, but any of the IJavaCompletionProposalComputer implementation don't receive the expected type as java.lang.String, which cause them to fail to provide suggestions. In this case the recommenders chain proposal provide fails.
Comment 6 Gayan Perera CLA 2019-01-20 11:34:24 EST
This is some refined simple code for this issue demo

package test;

import java.util.Arrays;

public class ASTChecks {
	public void print(String message) {
		
	}
	
	public void process(String...strings) {
		print();
	}
	
	public void processLambda1() {
		Arrays.asList(new String[][]{{"10"}, {"12"}}).forEach(a -> {print();});
	}
}


@Stephan the selectors as follows

in lambda print usage : There is no selector attribute
  - Node Type : CompletionOnSingleNameReference

in none lambda print usage : [p, r, i, n, t]
  - Node Type : CompletionOnMessageSend

One thing i notice if i don't end the lambda expression like without a semi colon like
> Arrays.asList(new String[][]{{"10"}, {"12"}}).forEach(a -> {print()});

Then

in lambda print usage : [p, r, i, n, t]
  - Node Type : CompletionOnMessageSend

Now this is very strange because i looked at the ASTtree using the ASTViewer there is not change in the tree with or without the semicolon. Seems like the completion AST tree is some what different in this case.
Comment 7 Eclipse Genie CLA 2021-01-10 17:52:26 EST
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet.

If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant.

--
The automated Eclipse Genie.
Comment 8 Eclipse Genie CLA 2021-04-22 17:02:07 EDT
New Gerrit change created: https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/179696
Comment 9 Stephan Herrmann CLA 2021-04-22 17:08:31 EDT
(In reply to Eclipse Genie from comment #8)
> New Gerrit change created:
> https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/179696

Here's a junit that demonstrates that after recent changes in an around bug 539685 we do have and use an expected type. (We still see CompletionOnSingleNameReference rather than CompletionOnMessageSend, but that seems to be fine - for arguments other than [0] it is necessary anyway). In fact it's probably bug 558530 that provides the expected type (see bug 558530 comment 4).

@Gayan, could you please verify that this also addresses your original issue?

*** This bug has been marked as a duplicate of bug 558530 ***
Comment 11 Jay Arthanareeswaran CLA 2021-05-26 02:35:40 EDT
Verified for 4.20 RC1 with build I20210525-1800