| Summary: | [completion] Null expectedType when resolving completions in lambda expressions. | ||
|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Gayan Perera <gayanper> |
| Component: | Core | Assignee: | 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: | |||
(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. @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.
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:> 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? @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. 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.
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. New Gerrit change created: https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/179696 (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 *** Gerrit change https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/179696 was merged to [master]. Commit: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=e6acd78ea2da8f35048b3bd85a7c2ce8c808f047 Verified for 4.20 RC1 with build I20210525-1800 |
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.