Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 132687 - Extract method refactoring does not analyze execution flow properly
Summary: Extract method refactoring does not analyze execution flow properly
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 enhancement (vote)
Target Milestone: 3.2 RC1   Edit
Assignee: Markus Keller CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-03-21 10:12 EST by Bernd Kolb CLA
Modified: 2006-05-05 18:02 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Bernd Kolb CLA 2006-03-21 10:12:22 EST
When trying to use the extract method refactoring on the following codeblock I got an messagebox which told me "Selected statements contain a return statement but not all possible execution flows end in a return"

public void foo(List list, Object constraint, int index) {
   Map m = new HashMap();
   if (list instanceof List) {
      List f= (List) list;
      if (f.size() == -1) {
         if (m.isEmpty()) {
            // do sth
         } else {
            for (Iterator iter= m.keySet().iterator(); iter.hasNext();) {
               // do sth
               for (Iterator iterator = Collections.EMPTY_LIST.iterator(); iterator.hasNext();) {
                  // do sth
                  if (true == false) {
                     // do sth
                     return;
                  }
                  // do sth
               }
            }
         }
      }
   }
}


What I expected to get was the following:
public void foo(List list, Object constraint, int index) {
   Map m = new HashMap();
   if (list instanceof List) {
      List f= (List) list;
      doSth(f, m);
   }
}


private void doSth(List f, Map m) {
   if (f.size() == -1) {
      if (m.isEmpty()) {
         // do sth
      } else {
         for (Iterator iter= m.keySet().iterator(); iter.hasNext();) {
            // do sth
            for (Iterator iterator = Collections.EMPTY_LIST.iterator(); iterator.hasNext();) {
               // do sth
               if (true == false) {
                  // do sth
                  return;
               }
               // do sth
            }
         }
      }
   }      
}
Comment 1 Markus Keller CLA 2006-03-22 13:05:43 EST
This is difficult in the general case. E.g. here, there's no easy way to extract the selection:

	void m(boolean b) {
		// -- extract
		if (b) {
			return;
		}
		// -- extract
		System.out.println("was here");
	}
Comment 2 Markus Keller CLA 2006-03-22 14:08:22 EST
Bernd has conviced me that the full-blown analysis and handling of the situation is often not required. It would already be helpful if the refactoring would not abort with a fatal error, but would just show an error and then do the extraction without considering the semantic shift of losing early returns.

We could make a small change in ExtractMethodAnalyzer#analyzeSelection() and adapt the error message to tell that early returns will be lost:

if (fReturnKind == UNDEFINED) {
	status.addError(RefactoringCoreMessages.FlowAnalyzer_execution_flow,
			JavaStatusContext.create(fCUnit, getSelection())); 
		fReturnKind= NO;
}

Dirk, what do you think?
Comment 3 Markus Keller CLA 2006-03-31 10:46:15 EST
Fixed in HEAD.