Community
Participate
Working Groups
public interface A_test1 { // creates default methods without body int i= aaa(); default void defaultM() { int a= bbb(); } static void staticM() { int x= ccc(); } } interface A_test2 { // creates static method without body int i = foo1(); static int foo() {return 0;} } interface A_test3 { // creates abstract method int i = foo2(); } ------------------------------------------------------------- In the above example, 'Create method' quick fix creates incorrect methods as given below: public interface A_test1 { // creates default methods without body int i= aaa(); default void defaultM() { int a= bbb(); } default int bbb(); default int aaa(); static void staticM() { int x= ccc(); } default int ccc(); } interface A_test2 { // creates static method without body int i = foo1(); static int foo() {return 0;} static int foo1(); } interface A_test3 { // creates abstract method int i = foo2(); int foo2(); } ------------------------------------------------------------- It should not create an abstract method in any case. Also, we should check if a default or a static method has to be created and create the correct method with body accordingly.
In the current implementation, if 'create method' quick fix is initiated from an interface, then the algorithm gets hold of the first method in the enclosing interface and copies its modifiers. Below are the clarifications required to continue the task: i) If the interface is enclosed in a class, then shouldn't the second quick fix create a 'static' method in the class, so that after the quick fix user does not have anymore errors to be fixed. ii) For Java 8, if the quick fix is initiated from the interface, then always create a static method, so that it can be accessed from an interface variable declaration, another static method or from a default method. iii) Couldn't come up with a valid case where an abstract method should be created when the quick fix is initiated from an interface. To sum it up, for less than Java 8, if 'create method' quick fix is initiated from an interface which is enclosed in a class, then the quick fix should create a static method in the class. In other cases no quick fix to create method should be provided. For Java 8, 2 quick fix proposal can be given, one to create the method within the interface and the other to create the method in the class if the interface is enclosed within a class. Kindly share your thoughts.
Before 1.8, the "Create method" quick fix was of limited value when it was invoked from a reference inside an interface member. In that case, the only valid situation was indeed when the interface was nested in a class, and the only applicable fix should be to create a static method in the enclosing class. (That proposal makes sense for 1.8 as well.) But note that this quick fix was mainly intended to be applied to references from outside of the interface declaration, e.g.: interface IContainer { public abstract String name(); } class Ref { void foo(IContainer c) { int[] v= c.values(); // create abstract IContainer#values() } } In that situation, it also makes sense to copy the modifiers of the first existing method declaration in the interface. Java 1.8 changes the game significantly, so we need adapted heuristics: (a) For references from outside the interface declaration, where the method invocation's expression has an interface type, the quick fix should keep creating an abstract method (since that's still the main intent of an interface). We should still use a heuristic to copy redundant public and abstract modifiers for new interface methods: 1. from the first abstract method, or if none available: 2. from the first method, or if none available: 3. from the first member Examples: void bar(Interface c) { int[] a= c.values(); // create abstract method Object o= Interface.getGlobal(); // create static method } (b) for references from inside an interface declaration (unqualified or qualified with "this."), it would be better to create a method that matches the static-ness of the enclosing member. I.e.: - for references from a default method, create an abstract method - for references from a static member, create a static method Examples: interface Container { default void doit() { Arrays.sort(this.values()); // create abstract } Object OBJ= init(); // create static }
Created attachment 234795 [details] Patch with testcases. With this patch i have covered most of the points Markus pointed out. In the below example, due to bug 414113 abstract method will not be created. But will be automatically fixed once the bug is resolved. interface Container { default void doit() { Arrays.sort(this.values()); // create abstract } } Markus, please review.
*** Bug 490742 has been marked as a duplicate of this bug. ***
(In reply to Manju Mathew from comment #3) > Created attachment 234795 [details] [diff] > Patch with testcases. > > With this patch i have covered most of the points Markus pointed out. The patch does not create an abstract method for an unqualified method reference from a default method: (In reply to Markus Keller from comment #2) > (b) for references from inside an interface declaration (unqualified or > qualified with "this."), it would be better to create a method that matches > the static-ness of the enclosing member. I.e.: > - for references from a default method, create an abstract method Also, the quick fix images are incorrect -- do not reflect the correct visibility of the method which will be created. I will upload a patch with these fixes.
Other issues to be fixed: It results in CCE if the invocation expression is an expression other than 'this' or a Name: java.lang.ClassCastException: org.eclipse.jdt.core.dom.ParenthesizedExpression cannot be cast to org.eclipse.jdt.core.dom.Name at org.eclipse.jdt.internal.ui.text.correction.proposals.NewMethodCorrectionProposal.evaluateModifiers(NewMethodCorrectionProposal.java:96) ... Also, it just refers to the modifiers of the first field and not the first member.
New Gerrit change created: https://git.eclipse.org/r/69983
Gerrit change https://git.eclipse.org/r/69983 was merged to [master]. Commit: http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/commit/?id=0e5f25311e184be60de67b2574d15abf17897acf