| Summary: | [1.8][assist] Code assist issues with type elided lambda parameters | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Srikanth Sankaran <srikanth_sankaran> | ||||||||
| Component: | Core | Assignee: | Srikanth Sankaran <srikanth_sankaran> | ||||||||
| Status: | RESOLVED FIXED | QA Contact: | |||||||||
| Severity: | normal | ||||||||||
| Priority: | P3 | CC: | anchakrk, daniel_megert, jarthana, markus.kell.r, noopur_gupta, shankhba, stephan.herrmann | ||||||||
| Version: | 4.4 | Flags: | srikanth_sankaran:
review?
(anchakrk) |
||||||||
| Target Milestone: | BETA J8 | ||||||||||
| Hardware: | PC | ||||||||||
| OS: | Windows 7 | ||||||||||
| Whiteboard: | |||||||||||
| Bug Depends on: | |||||||||||
| Bug Blocks: | 402079 | ||||||||||
| Attachments: |
|
||||||||||
Well, this is really bad for code completion. Members { methods | fields |
types } will be inaccessible unless we can infer the type and the skeletal
parse tree simply does not help. I think if an enclosing method of a lambda
with type elided parameter must be fully reconstructed for things to work
properly with elided types.
(In reply to Srikanth Sankaran from comment #1) > I think if an enclosing method of a lambda > with type elided parameter must be fully reconstructed for things to work > properly with elided types. Correction: Not the enclosing method, but the ExpressionStatement containing the lambda must be fully recovered. Relevant production from JLS(7): ExpressionStatement: StatementExpression ; StatementExpression: Assignment PreIncrementExpression PreDecrementExpression PostIncrementExpression PostDecrementExpression MethodInvocation ClassInstanceCreationExpression Assignment: LeftHandSide AssignmentOperator AssignmentExpression AssignmentExpression: ConditionalExpression Assignment LeftHandSide: ExpressionName FieldAccess ArrayAccess AssignmentOperator: one of = *= /= %= += -= <<= >>= >>>= &= ^= |= (In reply to Srikanth Sankaran from comment #2) > Correction: Not the enclosing method, but the ExpressionStatement containing > the lambda must be fully recovered. Current recovery strategy used by SelectionParser and CompletionParser are woefully inadequate for this task: i.e We cannot add more RecoveredElement abstractions for every kind of node type that would be involved. The list of productions from comment#2 are the top level productions. They will pull in other non terminals which will pull in other non terminals which will pull in other non terminals ... and so on. I'll prototype an alternate strategy. I have a very promising solution that works well for code select. Code complete is a a lot more trickier. Via http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=227e3d5fec0001fbc06115e3f3e6f09f357952e2, I released full support for selection inside lambda expressions including type elided parameter declarations and usages. Turned out that there is some prior art to such recovery past the selection point. It didn't lend itself to being extended for lambdas, but was useful to study to understand the issues. Anirban, please review. Shankha, this invalidates your patch yet again, please repost after fixing merge issues. It is likely we may get rid of the new RecoveredLambdaExpression abstraction altogether - I didn't want to prune it over-eagerly till code completion support is in place. Some preparatory work for fuller lambda recovery released here: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=96c4102f3d029f4dc8f7d84cd7957662a88272cf and here: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=f338c86815ffb4c165b8024ba4f28cade0b2b75f OK, I got the basics working:
In this program the line with the System.out.println call was completely
composed by code completion.
Still quite a ways to go with some major challenges.
// --
interface I {
void foo(Integer x);
}
public class X {
String xField;
static void goo(String s) {
}
static void goo(I i) {
}
public static void main(String[] args) {
goo((xyz) -> {
System.out.println(xyz.toString().concat("Hello").hashCode());
});
}
}
Created attachment 238163 [details]
Snap shot of work in progress
Just so if something should happen to my hard disk: here is a snap shot.
Many things work, many still don't, but the foundation is firmly in place.
Created attachment 238252 [details]
Patch v0.9
Down to four failures.
Quite of bit of clean up is required as there is lot of experimental code left in.
Expect to wrap this up tomorrow.
Created attachment 238301 [details] Patch v0.99 Tom Cargill is correct ! (http://en.wikipedia.org/wiki/Ninety-ninety_rule) :) Nearly there. All tests are green and most things work though there are a bunch of loose ends which I plan to address in follow up bugs. Just one final round of code review and clean up and I am ready to push this. Most importantly, the review should look into ascertaining that the algorithm will terminate ;-) Fix and tests released here: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?h=BETA_JAVA8&id=a98d7d87df415161ba75f53acbdbe8d316ea160c. Follow up tasks have been collected here: https://bugs.eclipse.org/bugs/show_bug.cgi?id=423987 Anirban, please review. Also take up verification of the entire code assist support to gauge what is still missing. |
BETA_JAVA8: At present, there are a set of problems in the way type elided lambda parameters are handled by SelectionEngine/SelectionParser. Similar but different issues exist with CompletionEngine/CompletionParser too. Given: // -- interface I { String foo(String x, Integer y); } public class X { static void foo(I i) {} public static void main(String[] args) { foo((x, y) -> x + y); } } (1) if you hover on either of x or y in x + y, we claim those are of type Object - this is blatantly wrong, but happens because the selection parser builds minimal parse trees in which a good bit of the pertinent contextual information is lost. The flattened parse tree for the method looks like: public static void main(String[] args) { (<no type> x, <no type> y) -> <SelectOnName:y>; } See that the fact about lambda being a method parameter is completely lost. I see this as requiring good amount of work to get correctly. Because lambda's can occur is deeply nested subexpressions, involving numerous node types, this is not going to be easy solution to "enhance" the selection/completion parser (2) If you hover on the parameter declaration, you get nothing. This is problematic as users will identify this as a classic situation where the IDE should help clarify things for them. (3) The hover on the use actually claims: Object y - X.main(String[]) This could perhaps be due to bug 416559 ? // -- Discussions welcome on how to go about solving this or alternate strategies.