Bug 562668

Summary: [1.8][extract method] Extract Method could produce records
Product: [Eclipse Project] JDT Reporter: Róbert Kitlei <kitlei>
Component: UIAssignee: JDT-UI-Inbox <jdt-ui-inbox>
Status: NEW --- QA Contact:
Severity: enhancement    
Priority: P3 CC: stephan.herrmann
Version: 4.16   
Target Milestone: ---   
Hardware: PC   
OS: Windows 10   
Whiteboard:

Description Róbert Kitlei CLA 2020-04-30 10:24:32 EDT
Supposing the user selects the two variable declaration statements and runs Extract Method, currently (as of Eclipse 4.16M1) the refactoring is denied with the message "Ambiguous return value", as both i and s are used later in the code.

public class ExtractMethod {
	public static void main(String[] args) {
		var i = 1;
		var s = "abc";
		System.out.println(i + s);
	}
}

Using the (preview) Java 14 feature of records, doing Extract Method is feasible. This is possibly the shortest variant.

public class ExtractMethod {
	public static void main(String[] args) {
		record I_S(int i, String s) {}

		var i_S = new I_S(1, "abc");
		System.out.println(i_S.i + i_S.s);
	}
}

Another possibility.

public class ExtractMethod {
	public static void main(String[] args) {
		var i_s = new I_S(1, "abc");
		System.out.println(i_s.i + i_s.s);
	}

	static record I_S(int i, String s) {}
}


Yet another possibility, putting the record in its own file.

public class ExtractMethod {
	public static void main(String[] args) {
		var i_s = new I_S(1, "abc");
		System.out.println(i_s.i() + i_s.s());
	}
}

// new file: I_S.java
public record I_S(int i, String s) {}
Comment 1 Stephan Herrmann CLA 2020-04-30 13:51:18 EDT
silly question: how is this "Extract Method", i.e., where is the extracted method?
Comment 2 Róbert Kitlei CLA 2020-05-19 21:13:40 EDT
You're right in pointing out that the method is missing. I take it that you didn't mean to be rude: it's not a silly request at all, only somewhat mislabeled. The feature described in my original question could be a new refactoring called Introduce Record.

Anyway, here's a possible output of Extract Method applied to the two vars in the original code where the method does make its appearance.

public class ExtractMethod {
	public static void main(String[] args) {
		var i_S = i_s();
		System.out.println(i_S.i + i_S.s);
	}

	static record I_S(int i, String s) {}

	private static I_S i_s() {
		var i = 1;
		var s = "abc";
		return new I_S(i, s);
	}
}

Using Inline on both i and s in the new method gives us:

private static I_S i_s() {
	return new I_S(1, "abc");
}

... and inlining the invocation of i_s() gives us:

public class ExtractMethod {
	public static void main(String[] args) {
		var i_S = new I_S(1, "abc");
		System.out.println(i_S.i + i_S.s);
	}

	static record I_S(int i, String s) {}
}

... which is effectively the second version that I've listed previously.