Bug 329663 - [type hierarchy] Interfaces duplicated in type hierarchy on two packages from multiple projects
Summary: [type hierarchy] Interfaces duplicated in type hierarchy on two packages from...
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.7   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 3.7 M4   Edit
Assignee: Jay Arthanareeswaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-11-08 06:02 EST by Deepak Azad CLA
Modified: 2011-04-26 09:49 EDT (History)
4 users (show)

See Also:


Attachments
screenshot (39.62 KB, image/png)
2010-11-08 06:02 EST, Deepak Azad CLA
no flags Details
Patch for UI (1.36 KB, patch)
2010-11-09 04:28 EST, Raksha Vasisht CLA
no flags Details | Diff
Proposted patch with test (4.10 KB, patch)
2010-11-10 03:16 EST, Jay Arthanareeswaran CLA
no flags Details | Diff
Updated patch (4.65 KB, patch)
2010-11-23 04:08 EST, Jay Arthanareeswaran CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Deepak Azad CLA 2010-11-08 06:02:05 EST
Created attachment 182599 [details]
screenshot

I20101028-1441

Steps
- Select the following 2 packages in PE
org.eclipse.jdt.internal.ui.text.spelling
org.eclipse.ui.texteditor.spelling
- F4
- Couple of interfaces are repeated in the Type Hierarchy (see attached screenshots) 

This happens only when both packages are in different projects, and there is some class that implements the interface in both packages. But if both packages are in same project there is no duplication.

Simple test case
*Project X*
package p;
public interface IA {
}

package p;
class A implements IA {
	void foo() {		
	}
}

package p;
class B implements IA {
	void foo() {		
	}
} 

*Project Y*
package q;
import p.IA;
class C implements IA {
	void foo() {		
	}
}

package q;
import p.IA;
class D implements IA {
	void foo() {		
	}
}

Is the duplication deliberate and supposed to mean anything? Or it is just a bug?
Comment 1 Dani Megert CLA 2010-11-08 07:03:10 EST
Looks like a bug to me. Raksha please investigate.
Comment 2 Raksha Vasisht CLA 2010-11-09 04:28:18 EST
Created attachment 182687 [details]
Patch for UI

From the example above, the Interface IA occurs in the hierarchy twice as the Region based hierarchy itself contains the same interface twice when the packages are in different projects but occurs only once when the packages containing types implementing the same interface in the same project. We can fix it in UI with a single line fix but the actual fix will have to be done in Core while calculating the region based hierarchy.

We call the core API from 
org.eclipse.jdt.internal.ui.typehierarchy.TraditionalHierarchyViewer.TraditionalHierarchyContentProvider.getRootTypes(...)

The core API 
org.eclipse.jdt.core.ITypeHierarchy.getRootInterfaces() which in turn calls
 org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy.getAllInterfaces() returns the interface twice when the packages containing types implementing the same interface are in different projects. Here's the stack trace to how the interfaces are added to the hierarchy:

Thread [Worker-8] (Suspended (breakpoint at line 200 in TypeHierarchy))	
	RegionBasedTypeHierarchy(TypeHierarchy).addInterface(IType) line: 200	
	RegionBasedHierarchyBuilder(HierarchyBuilder).connect(IGenericType, IType, IType, IType[]) line: 170	
	HierarchyResolver.reportHierarchy(IType, TypeDeclaration, ReferenceBinding) line: 532	
	HierarchyResolver.resolve(Openable[], HashSet, IProgressMonitor) line: 809	
	RegionBasedHierarchyBuilder.createTypeHierarchyBasedOnRegion(HashMap, IProgressMonitor) line: 90	
	RegionBasedHierarchyBuilder.build(boolean) line: 59	
	RegionBasedTypeHierarchy.compute() line: 97	
	RegionBasedTypeHierarchy(TypeHierarchy).refresh(IProgressMonitor) line: 1263	
	CreateTypeHierarchyOperation.executeOperation() line: 90	
	CreateTypeHierarchyOperation(JavaModelOperation).run(IProgressMonitor) line: 728	
	CreateTypeHierarchyOperation(JavaModelOperation).runOperation(IProgressMonitor) line: 788	
	JavaCore.newTypeHierarchy(IRegion, WorkingCopyOwner, IProgressMonitor) line: 3980	
	TypeHierarchyLifeCycle.createTypeHierarchy(IJavaElement[], IProgressMonitor) line: 314	
	TypeHierarchyLifeCycle.doHierarchyRefresh(IJavaElement[], IProgressMonitor) line: 328	
	TypeHierarchyLifeCycle.doHierarchyRefreshBackground(IJavaElement[], IProgressMonitor) line: 269	
	TypeHierarchyLifeCycle$2.run(IProgressMonitor) line: 222	
	Worker.run() line: 54	


Dani, should I move this bug to Core and use the patch temporarily?
Comment 3 Markus Keller CLA 2010-11-09 07:04:16 EST
(In reply to comment #2)
The bug is in the implementation of ITypeHierarchy.getRootInterfaces(), moving to JDT/Core.

We don't need a workaround in JDT/UI, since this is not major, not a new problem, and JDT/Core has enough time to fix it for 3.7.
Comment 4 Olivier Thomann CLA 2010-11-09 09:27:39 EST
Jay, please investigate.
Comment 5 Jay Arthanareeswaran CLA 2010-11-10 03:16:46 EST
Created attachment 182787 [details]
Proposted patch with test

Raksha, could you please see if this patch is enough?
Comment 6 Raksha Vasisht CLA 2010-11-10 04:05:56 EST
(In reply to comment #5)
> Created an attachment (id=182787) [details] [diff]
> Proposted patch with test
> 
> Raksha, could you please see if this patch is enough?

Yep, that would remove duplicacy. Thanks Jay.
Comment 7 Markus Keller CLA 2010-11-10 08:10:24 EST
(In reply to comment #5)
> Created an attachment (id=182787) [details] [diff]

Please make sure this doesn't introduce a performance regression. Unlike the field this.rootClasses, the list this.interfaces may contain a lot of elements, and if addInterface(..) is called often, then this could be a bottleneck (e.g. for a type hierarchy on the whole rt.jar).

As an alternative, you could probably use the typeToSuperInterfaces map to quickly check whether the type is already known. That would replace the O(n) ArrayList#contains(..) with better scaling hash lookup.
Comment 8 Jay Arthanareeswaran CLA 2010-11-15 07:11:31 EST
(In reply to comment #7)
> (In reply to comment #5)
> > Created an attachment (id=182787) [details] [details] [diff]
> 
> Please make sure this doesn't introduce a performance regression. Unlike the
> field this.rootClasses, the list this.interfaces may contain a lot of elements,
> and if addInterface(..) is called often, then this could be a bottleneck (e.g.
> for a type hierarchy on the whole rt.jar).
> 
> As an alternative, you could probably use the typeToSuperInterfaces map to
> quickly check whether the type is already known. That would replace the O(n)
> ArrayList#contains(..) with better scaling hash lookup.

Thanks for the suggestion, Markus. I ran some performance tests and did notice some noticeable performance dip, albeit small, with the existing patch as is. Doing the contains check against typeToSuperInterfaces and inside HierarchyBuilder#connect() keeps the performance degrade negligible, if at all any. I will collect some numbers and post the new patch.
Comment 9 Jay Arthanareeswaran CLA 2010-11-23 04:08:10 EST
Created attachment 183646 [details]
Updated patch

This patch has lesser performance impact, if any. 
A region based hierarchy construction on rt.jar produces numbers like below.

With HEAD:
    Elapsed Process:        5.86m         
    CPU Time:               4.07m        

With the patch:
    Elapsed Process:        5.91m         
    CPU Time:               4.06m 

Subsequent runs produces varying numbers at times the patch producing better numbers. But on an average, things haven't changed much with the patch.
Comment 10 Jay Arthanareeswaran CLA 2010-11-29 08:57:51 EST
Released in HEAD for 3.7 M4.
Comment 11 Jay Arthanareeswaran CLA 2010-11-29 08:58:37 EST
.
Comment 12 Olivier Thomann CLA 2011-04-26 09:49:03 EDT
Verified.