Bug 181981 - [model] Linked Source Folders with Parallel package structure do not work with occurrences
Summary: [model] Linked Source Folders with Parallel package structure do not work wit...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.2.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.4 M5   Edit
Assignee: Jerome Lanneluc CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-04-11 13:40 EDT by Igor Lubashev CLA
Modified: 2008-02-04 16:06 EST (History)
3 users (show)

See Also:


Attachments
Sample project to illustrate the problem (1.87 KB, application/x-zip-compressed)
2007-04-17 14:47 EDT, Igor Lubashev CLA
no flags Details
Proposed fix and regression test (7.62 KB, patch)
2008-01-10 10:44 EST, Jerome Lanneluc CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Igor Lubashev CLA 2007-04-11 13:40:58 EDT
Build ID: M20070212-1330

Steps To Reproduce:
My source tree looks like:
  foo/
    /src
      /com
        /bar
          etc
    /qa
      /src
        /com
          /bar
             etc

1. Make a Project with source pointing to /foo
2. Link folder qa to project, and call it "qa".  Of course, set up exclusion filter on the main project to exclude qa/
3. Everything compiles nicely into a single proper output tree

4. But if you try to refactor, you get an error that "qa.com.foo.Baz cannot be found".  Likewise, when you do a Reference Search, the references show up as "qa.com.foo.Baz", a question mark for the package icon, but the file itself is availabel and can be opened.


More information:
Comment 1 Jerome Lanneluc CLA 2007-04-12 06:53:02 EDT
What kind of refactoring do you do ?
Comment 2 Igor Lubashev CLA 2007-04-12 14:18:15 EDT
Oh, anything, really.  Let's say, "rename a method".

Just make sure that the method being renamed belongs to a class defined in "foo/src/com/bar/..." tree, and it is called from a class that belongs to "foo/qa/src/com/bar/..." tree.

The root cause seems to be in how Eclipse is resolving package names for classes on the linked folder called "qa".  Even without refactoing, when you do a Reference Search, the references show up as "qa.com.foo.Baz", and a question mark for the package icon is a tell-tale sign that something is looking for a package name that starts with "qa" and cannot find it.
Comment 3 Jerome Lanneluc CLA 2007-04-13 09:21:01 EDT
The problem with search is a separate issue. Please enter a separate bug report.

Moving to JDT/UI for investigating why the rename refactoring fails this way.
Comment 4 Markus Keller CLA 2007-04-17 08:41:12 EDT
Can you zip up the example project and attach it? I don't understand how exactly your project setup looks like.
Comment 5 Igor Lubashev CLA 2007-04-17 14:47:16 EDT
Created attachment 64079 [details]
Sample project to illustrate the problem

Expand this zip file.  The project file is in prj/src/.project .
proj/qa/src must be linked as "qa".

Open class Foo.

If you try "refactor"/"rename" method someMethod() to fooMethod(), you would see that the invocation in qa/com.bar.Bar has not been updated.

If you try "refactor"/"change method signature" and change the name of the method from someMethod() to fooMethod() there, you get:

"An unexpected exception occured while prforming the refactorying. See error log for more details.

Reason:
 qa.com.bar [in <project root> [in Project]] does not exist"

Here is the error log entry.

Java Model Exception: Java Model Status [qa.com.bar [in <project root> [in Project]] does not exist]
at org.eclipse.jdt.internal.core.JavaElement.newNotPresentException(JavaElement.java:485)
at org.eclipse.jdt.internal.core.PackageFragment.buildStructure(PackageFragment.java:72)
at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:229)
at org.eclipse.jdt.internal.core.Openable.openParent(Openable.java:420)
at org.eclipse.jdt.internal.core.CompilationUnit.openParent(CompilationUnit.java:1065)
at org.eclipse.jdt.internal.core.Openable.generateInfos(Openable.java:218)
at org.eclipse.jdt.internal.core.JavaElement.openWhenClosed(JavaElement.java:505)
at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:249)
at org.eclipse.jdt.internal.core.JavaElement.getElementInfo(JavaElement.java:235)
at org.eclipse.jdt.internal.core.Openable.getBuffer(Openable.java:255)
at org.eclipse.jdt.core.dom.rewrite.ASTRewrite.rewriteAST(ASTRewrite.java:239)
at org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite.attachChange(CompilationUnitRewrite.java:206)
at org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite.createChange(CompilationUnitRewrite.java:172)
at org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite.createChange(CompilationUnitRewrite.java:157)
at org.eclipse.jdt.internal.corext.refactoring.structure.ChangeSignatureRefactoring.createChangeManager(ChangeSignatureRefactoring.java:1294)
at org.eclipse.jdt.internal.corext.refactoring.structure.ChangeSignatureRefactoring.checkFinalConditions(ChangeSignatureRefactoring.java:812)
at org.eclipse.ltk.core.refactoring.CheckConditionsOperation.run(CheckConditionsOperation.java:83)
at org.eclipse.ltk.core.refactoring.CreateChangeOperation.run(CreateChangeOperation.java:118)
at org.eclipse.ltk.core.refactoring.PerformChangeOperation.run(PerformChangeOperation.java:189)
at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1737)
at org.eclipse.ltk.internal.ui.refactoring.WorkbenchRunnableAdapter.run(WorkbenchRunnableAdapter.java:87)
at org.eclipse.jface.operation.ModalContext$ModalContextThread.run(ModalContext.java:113)
Comment 6 Markus Keller CLA 2007-04-18 11:47:32 EDT
Thanks Igor, the sample project makes it much easier to reproduce:
Extract the zip to C:\temp\ and import it as existing project (without copying).

The problems in the refactorings are actually caused by problems in the search engine when searching for occurrences (in HEAD):

- search for references to com.foo.Foo.someMethod()
=> correctly finds barMethod with handleIdentifier "=Project/qa<com.bar{Bar.java[Bar~barMethod"

- search for occurrences of com.foo.Foo.someMethod()
=> finds declaration and a non-existing barMethod with handleIdentifier "=Project/<qa.com.bar{Bar.java[Bar~barMethod"

There's a problem with "com.bar" in source folder "qa". Moving to core.
Comment 7 Frederic Fusier CLA 2008-01-10 03:06:18 EST
This is not a search issue as Search Engine correctly finds the reference to the method in Bar. The real problem comes from the HandleFactory.createOpenable(String , IJavaSearchScope) method.

While searching just for reference, there's only one processed SearchDocument: /Project/qa/com/bar/Bar.java and the factory creates the handle in the correct package fragment root: the source folder 'qa'.

But while renaming, JDT/UI calls Search Engine using a combined pattern to search for both declaration and references. So, there are two SearchDocument in the loop:
/Project/com/foo/Foo.java 
/Project/qa/com/bar/Bar.java 

Then the factory, first creates the handle for Foo which is in the <default> package fragment root. So, when creating the handle for Bar, the following test:
if (this.lastPkgFragmentRootPath == null 
|| !(resourcePath.startsWith(this.lastPkgFragmentRootPath) 
&& (rootPathLength = this.lastPkgFragmentRootPath.length()) > 0
&& resourcePath.charAt(rootPathLength) == '/')) {

is wrongly true and the <default> package is still used for this compilation although it should call the getPkgFragmentRoot(resourcePath) to get the correct package fragment root 'qa'...

Comment 8 Frederic Fusier CLA 2008-01-10 03:25:36 EST
Note that the source folder does not need to be linked. It fails the same way with simple following set-up:

/P
 + qa (src folder)
   + com
     + bar
       + Bar.java
 + com
   + foo
     + Foo.java
   + test
     + Test.java

If in com.test.Test you have also a method calling Foo.someMethod(), then you can directly see the problem in Search view while searching for method references:
/P
 - com.test
   - Test
     ^ testMethod()
 - ? qa.com.bar
   - ? Bar
     - ? barMethod()
Comment 9 Jerome Lanneluc CLA 2008-01-10 10:44:28 EST
Created attachment 86561 [details]
Proposed fix and regression test
Comment 10 Jerome Lanneluc CLA 2008-01-10 10:49:03 EST
Fix and test released for 3.4M5
Comment 11 Kent Johnson CLA 2008-02-04 16:06:48 EST
Verified for 3.4M5 using I20080204-0010