Bug 427169 - [1.8][quick assist] lambda body: convert expression to block
Summary: [1.8][quick assist] lambda body: convert expression to block
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.4   Edit
Hardware: All All
: P3 enhancement (vote)
Target Milestone: BETA J8   Edit
Assignee: Noopur Gupta CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-01-31 17:30 EST by Stephan Herrmann CLA
Modified: 2014-02-21 01:19 EST (History)
5 users (show)

See Also:
markus.kell.r: review+


Attachments
WIP Patch (11.16 KB, patch)
2014-02-05 11:13 EST, Noopur Gupta CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Stephan Herrmann CLA 2014-01-31 17:30:28 EST
I was playing with a lambda with a simple expression, and then I wanted to add slightly more logic which required me to use a block instead of the expression.

Wouldn't it be cool if JDT/UI offered a quick assist

   "Convert body expression to block"? :)

To convert this:

	void assistDemo(boolean flag) {
		perform(() -> 13); 
	}

into this:

	void assistDemo(boolean flag) {
		perform(() -> {
			return 13;
		}); 
	}


(And perhaps the inverse, too, if possible).
Comment 1 Noopur Gupta CLA 2014-02-03 09:35:02 EST
We can also provide these as clean up options along with the quick assists.

The clean up could be similar to:
Code Style -> Control statements -> Use blocks...

Should these be added in a separate group for lambda expressions on the Code Style page?
Comment 2 Stephan Herrmann CLA 2014-02-03 12:49:19 EST
(In reply to Noopur Gupta from comment #1)
> We can also provide these as clean up options along with the quick assists.
> 
> The clean up could be similar to:
> Code Style -> Control statements -> Use blocks...

I see the analogy, but actually I doubt that people would use that clean-up. After all, lambdas are all about code brevity, so single expressions will usually stay block-less, I guess. 
I see it more as an issue during editing, when code gets more complex..
Comment 3 Markus Keller CLA 2014-02-04 06:52:18 EST
Yes, let's just add quick assists for now (in both directions).

Later, we could even integrate this into the existing "Use blocks in ..." cleanup option (i.e. no separate option just for lambdas).

And let's reuse the terminology of similar existing quick assists for if/while/... statements:
- Change body expression to block
- Change body block to expression
Comment 4 Noopur Gupta CLA 2014-02-05 11:13:08 EST
Created attachment 239665 [details]
WIP Patch

The patch can be applied to mmathew/BETA_JAVA8 branch.
It provides 2 quick assists:

- Change body expression to block: 
If the return type of lambda is 'void', ExpressionStatement is created.
Otherwise, ReturnStatement is created.

- Change body block to expression:
Available only when the single statement in the lambda body is a ReturnStatement or an ExpressionStatement (with expression being a valid body of lambda).
(Checked all the sub-classes of Statement and ExpressionStatement to find the valid cases).

TODO:
- Add tests.
- The "Change body block to expression" quick assist, when applied to a lambda body containing a single statement along with some comments, does not preserve the comments currently. 
Example:
	FI1 fi1 = x -> { 
		// comment1
		return x; // comment2
		// comment3
	};

will result in:
        FI1 fi1 = x -> x;

Markus, how can we preserve the comments or disable the quick assist when there are comments in the lambda body?
Comment 5 Markus Keller CLA 2014-02-06 08:11:23 EST
(In reply to Noopur Gupta from comment #4)

In both new QuickAssistProcessor methods, this statement should appear earlier in the code, before the 'ASTRewrite.create(..)' call:

		if (resultingCollections == null)
			return true;

The quick assist infrastructure always calls _all_ these get*Proposals(..) methods in hasAssists(..) to check whether assists are available at all. This should be quick, and we should not create an ASTRewrite unless we know we're actually going to use it to create a proposal.

> Markus, how can we preserve the comments or disable the quick assist when
> there are comments in the lambda body?

I don't see a simple solution. I looked at the other 'Change xxx to block/statement' quick assists, but the difference here is that there's no good place to put the comments at all. I would just ignore the problem for now and let the comments disappear. Bug 424266 is about the same problem in a sightly different context, but the solution to both problems will work the same way.

And this bug is about a quick assist, so the removal of the comments happens in the user's sight. That's less severe than if it happens in a Clean Up.
Comment 6 Noopur Gupta CLA 2014-02-06 09:14:16 EST
Released into BETA_JAVA8 after moving the "if (resultingCollections == null)" condition as mentioned in comment #5 and adding the tests.

http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/commit/?h=BETA_JAVA8&id=b119a29fa393e16e5c068d6ec8a155c4a7f9df11

Keeping the bug open, in case some changes are required after review.
Comment 7 Markus Keller CLA 2014-02-06 15:03:38 EST
getChangeLambdaBodyToExpressionProposal(..) should also do the whole analysis before creating an ASTRewrite.

I've also increased the relevance of the proposals, because I think they will be used more often than "Convert to anonymous".

Finished up with http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/commit/?id=23dfea26642d6307c698c3c91e53a0dfaa50baae
Comment 8 shankha banerjee CLA 2014-02-21 00:51:35 EST
Have the following piece of code:

package snippet;

public class Snippet {
	interface I {
			int add();
	}
	void perform(I i) {}
	
	void assistDemo(boolean flag) {
			perform(() -> 13); 
		}
	
}

Place cursor on -> and Ctrl 1. 
The transformation from expression to block takes place correctly.

Verified for Eclipse Kepler 4.3.2 RC4 Build id: M20140212-0800.
Comment 9 shankha banerjee CLA 2014-02-21 01:19:31 EST
Verified as working for Eclipse + Java 8 RC1 Eclipse Kepler 4.3.2(RC4) Build id: M20140212-0800 +  
Eclipse Java Development Tools Patch for Java 8 Support (BETA)	
1.0.0.v20140220-2054.