Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 408114 - [1.8][extract local] Unable to extract local variable within lambda expression's body
Summary: [1.8][extract local] Unable to extract local variable within lambda expressio...
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.3   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 4.5 M3   Edit
Assignee: Noopur Gupta CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 405305
  Show dependency tree
 
Reported: 2013-05-15 07:59 EDT by Noopur Gupta CLA
Modified: 2014-09-30 04:19 EDT (History)
3 users (show)

See Also:
markus.kell.r: review+


Attachments
Patch (25.51 KB, patch)
2014-09-29 06:14 EDT, 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 Noopur Gupta CLA 2013-05-15 07:59:16 EDT
Since a lambda expression is like a method, it should be possible to extract local variables within its body.

Consider the following example and try to extract a local variable from the lines with comments, we get different error messages:

@FunctionalInterface
interface FI {
	int foo(int a);
}

public class TestExtractLocalVariable {
	FI fi1= (a) -> a + 10;	// Error
	
	FI fi2= (int a) -> {	
		int b= a + 10; // Error
		return b;
	};
	
	void bar(FI fi) {
	     FI fi1= (a) -> a + 10; // Error, not extracted within lambda body
		
	     FI fi2= (a) -> {	
		    int b= a + 10; // Works here
		    return b;
	     };		
	}	
}
Comment 1 Noopur Gupta CLA 2014-09-29 06:14:09 EDT
Created attachment 247437 [details]
Patch

Attached fix and tests to extract local variable in lambda expression's body.
Markus, please have a look.
Comment 2 Markus Keller CLA 2014-09-29 15:15:30 EDT
Looks good, thanks.

Nits:

* The separate message constant is not really necessary, since the addition of "lambda expression" is not wrong for earlier versions of Java. I'd favor less code and less messages over a sightly more concise message for a soon-to-be-EOL'd language version.

* Better use Bindings.isVoidType(..) instead of ast.resolveWellKnownType("void").isEqualTo(..)

* The double casts here are not too nice:
    SimpleName varName= ((VariableDeclarationFragment) ((VariableDeclarationStatement) replacement).fragments().get(0)).getName();

Better extract "createTempDeclaration(initializer)", remove the comment, and use the new local variable that already has the right type.

The other cast can be avoided by extracting this local variable:

    List<VariableDeclarationFragment> fragments= tempDeclaration.fragments();

This works because the jdt.ui project has the "Ignore unavoidable generic type problems due to raw APIs" warning enabled.
Comment 3 Markus Keller CLA 2014-09-29 15:19:57 EDT
(In reply to Markus Keller from comment #2)
> This works because the jdt.ui project has the "Ignore unavoidable generic
> type problems due to raw APIs" warning enabled.

I meant: ... the ... *option* enabled.

That option can fix "type safety" problems, but it cannot insert casts, since that would make the compiler deviate from the JLS.
Comment 4 Noopur Gupta CLA 2014-09-30 04:19:45 EDT
Thanks Markus. Updated the patch as per review comments and released as:
http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/commit/?id=4f588b97a34c99264ee85309e6786c822be612ed