Bug 99355 - extract method trips up with generics and final variables
Summary: extract method trips up with generics and final variables
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.1 RC3   Edit
Assignee: Olivier Thomann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-06-10 09:48 EDT by Nikolay Metchev CLA
Modified: 2005-06-16 13:56 EDT (History)
1 user (show)

See Also:


Attachments
Screen shot showing the three final modifiers in the AST view (2.82 KB, image/png)
2005-06-12 16:42 EDT, Dirk Baeumer CLA
no flags Details
But in the AST converter parsing of modifiers (2.99 KB, patch)
2005-06-13 11:25 EDT, Olivier Thomann CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Nikolay Metchev CLA 2005-06-10 09:48:04 EDT
if you extract method where indicated below. you will see that the extracted
method declares its paramater with too many final modifiers:
-------------------------------------

package p;

class Container<T>
{
   private final T m_t;

   public Container(T t)
   {
      m_t = t;
   }

   T get()
   {
      return m_t;
   }
}

class GenericContainer
{
   private final Container<?> m_c;

   public GenericContainer(Container<?> c) 
   {
      m_c = c;
   }

   public Container<?> getC()
   {
      return m_c;
   }
}

public class A
{
   GenericContainer createContainer()
   {
      final Container<String> innerContainer = new Container<String>("hello");
      final Container<Container<String>> outerContainer = new
Container<Container<String>>(innerContainer);
      return new GenericContainer(outerContainer);
   }
   
   void method()
   {
      final GenericContainer createContainer = createContainer();
      @SuppressWarnings("unchecked")
      final Container<Container<String>> c = (Container<Container<String>>)
createContainer.getC();
      //extract method from here
      final Container<String> container = c.get();
      final String string = container.get();
      //to here
   }
}
-----------------------------------------------
results in
-----------------------------------------------

package p;

class Container<T>
{
   private final T m_t;

   public Container(T t)
   {
      m_t = t;
   }

   T get()
   {
      return m_t;
   }
}

class GenericContainer
{
   private final Container<?> m_c;

   public GenericContainer(Container<?> c) 
   {
      m_c = c;
   }

   public Container<?> getC()
   {
      return m_c;
   }
}

public class A
{
   GenericContainer createContainer()
   {
      final Container<String> innerContainer = new Container<String>("hello");
      final Container<Container<String>> outerContainer = new
Container<Container<String>>(innerContainer);
      return new GenericContainer(outerContainer);
   }
   
   void method()
   {
      final GenericContainer createContainer = createContainer();
      @SuppressWarnings("unchecked")
      final Container<Container<String>> c = (Container<Container<String>>)
createContainer.getC();
      //extract method from here
      extractedMethod(c);
      //to here
   }

   private void extractedMethod(final final final Container<Container<String>> c)
   {
      final Container<String> container = c.get();
      final String string = container.get();
   }
}
-----------------------------------------------------------

notice the 3 final modifiers in the extractedMethod signature.
Comment 1 Nikolay Metchev CLA 2005-06-10 09:49:39 EDT
Eclipse 3.1RC1, JDK 1.5.0_03
Comment 2 Dirk Baeumer CLA 2005-06-10 11:15:43 EDT
Still exists in RC2 candidate.
Comment 3 Dirk Baeumer CLA 2005-06-12 16:41:27 EDT
The problem is that the underlying AST already contains three final modifiers
for the declaration:

final Container<Container<String>> c = (Container<Container<String>>)
createContainer.getC();

Since the variable C is passed to the method the refactoring creates a new
parameter and copies the modifiers from the declaration. The ASTFlattener then
puts three final strings into the source code.

Moving to JDT/Core. 

Philippe, IMO we should consider this for RC3 since none of the tooling
currently expects doubled modifiers.
Comment 4 Dirk Baeumer CLA 2005-06-12 16:42:07 EDT
Created attachment 22873 [details]
Screen shot showing the three final modifiers in the AST view
Comment 5 Philipe Mulet CLA 2005-06-12 16:44:26 EDT
+1 for RC3

Dirk - pls append your vote.
Comment 6 Dirk Baeumer CLA 2005-06-12 16:50:52 EDT
+1 for RC3.
Comment 7 Nikolay Metchev CLA 2005-06-13 04:19:22 EDT
P.S. I forgot to mention that in the original code that this occured the end
result was a little more drastic. There was a lot more than 3 final modifiers
(around about 10). However even more bizzarely there were a few private
modifiers scattered in between the final modifiers. 
I hope that by code expection it is possible to see how those things could have
happend. If not please let me know and I will try and come up with a test case.
Comment 8 Olivier Thomann CLA 2005-06-13 10:59:28 EDT
Reproduced. I am investigating.
Comment 9 Olivier Thomann CLA 2005-06-13 11:25:13 EDT
Created attachment 22935 [details]
But in the AST converter parsing of modifiers

Proposed patch.
Comment 10 Olivier Thomann CLA 2005-06-13 11:29:07 EDT
Fixed and released in HEAD.
Regression test added in org.eclipse.jdt.core.tests.dom.ASTConverter15Test.test190
Comment 11 David Audel CLA 2005-06-16 13:56:43 EDT
Verified using build N20050616-0010 + JDT Core HEAD.