Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 321411

Summary: [hierarchy] Replace OTTypeHierarchy with adapting the original TypeHierarchy
Product: [Tools] Objectteams Reporter: Stephan Herrmann <stephan.herrmann>
Component: OTDTAssignee: Stephan Herrmann <stephan.herrmann>
Status: VERIFIED FIXED QA Contact:
Severity: normal    
Priority: P3    
Version: 0.7   
Target Milestone: 0.7.1   
Hardware: PC   
OS: Linux   
Whiteboard:
Attachments:
Description Flags
proposed implementation
none
More migration
none
Still more migration none

Description Stephan Herrmann CLA 2010-07-30 19:03:28 EDT
Currently OTTypeHierarchy.getSuperclass(IType) throws 
UnsupportedOperationException for roles because roles have multiple supers.

However, too many parts of the JDT rely on this functions. So we should
try harder to implement that method in a way the truthfully reflects the
semantics of OT/J.

Given that we implicitly support a linearization of superclasses we might
use IType wrappers that internally store the full superclass graph 
together with a cursor where in this hierarchy we are while ascending using
getSuperclass(IType).
Comment 1 Stephan Herrmann CLA 2010-07-31 13:29:09 EDT
Initial work on this issue shows that it should be much easier to replace
OTTypeHierarchy with an adaptation layer on top of the original 
TypeHierarchy. Adjusting bug title to reflect the change in strategy.
Comment 2 Stephan Herrmann CLA 2010-08-12 13:50:44 EDT
Created attachment 176486 [details]
proposed implementation

This is the initial implementation of an OT/J-based alternative to the
old OTTypeHierarchy:

* New Team OTTypeHiearchies adapts TypeHierarchy and friends
  - role OTHierarchyBuilder intercepts new join point builder.hookableConnect,
    in order to connect types along implicit inheritance.
  - nested team OTTypeHierarchy intercepts several top-level queries of
    TypeHiearchy in order to handle the following:
    - unwrap OTTypes
    - filter/substitute phantom roles in result
    - compute superclasses/supertypes in considering implicit inheritance, too.
  - nested role OTTypeHierarchy.ConnectedType contains the additional wiring
    - direct tsupers, all known tsubs, linearized tsupers, root of chain
    - phantom flag, enum-tag of where in the hierarchy we are 
      (relative to focus type)
  - key trick is to intercept TypeHierarchy.getSuperclass() and answer the next
    element from the linearized list of tsupers (as looking from focus type)
  - the team provides several API methods for additional queries 
    (actual hierarchy is passed as an argument).
* Prepare core classes for adaptation
  - type hierarchy unwraps any OTTypes
  - IndexBasedHierarchyBuilder additionally traverses from roles to their 
    enclosing team to cover team inheritance and thus implicit inheritance.
    TODO: check if this is sufficient in the case of role files.
  - HierarchyResolver & HierarchyBuilder:
    - swaps order: first completeTypeBindings and only then report
      (rememberAllTypes), to ensure copied roles are captured, too.
    - for purely copied roles create a HierarchyType as the IGenericType
    - pass more information into builder.connect (new wrapper hookableConnect),
      which serves as a join point for the OTTypeHierarchies team:
        tsuper classes, phantom flags, and the original compiler bindings
    - greatly simplify subTypeOfType by using roleModel.getTSuperRoleBindings()
* Extend super-ref entries in index to include AccRole (incr. index version)

Note that the hierarchy works slightly different for the focus types vs. its
sub/supertypes:
* for types below the focus type, no supertypes that are unrelated to the 
  focus type will be answered.

Single remain issue is witnessed as a regression in
 CompleteRoleHierarchyWithClasses.testGetAllSuperclasses_ofImplSuperSuperRole()
When querying all supertypes (or classes) of a type above the focus role, 
after traversing tsupers the regular supers of the focus type will be answered.
Comment 3 Stephan Herrmann CLA 2010-08-12 14:28:45 EDT
Patch has been committed as r676/r677 (plus a little update in r678).

OT hierarchy tests have been migrated in r679:

Migrate all OT hierarchy tests to the new OT/J based implementation.

Changes in test cases:
- OTSuperTypeHierarchyTest013 has a clash of incompatible "extends", don't
  expect all these types to be reported as superclasses
- OTSuperTypeHierarchyTest011: fix handle for nested phantom role & test it
- OTSuperTypeHierarchyTest009: expect new behavior of getSuperclass
- OTSuperTypeHierarchyTest008: new tests for type below the focus type
- OTSuperTypeHierarchyTest007: bugfix.
- OTSuperTypeHierarchyTest001: new test for linearization through repeated calls
  to getSuperclass()
- OTSubTypeHierarchyTest017: several bugfixes
  - type not a subtype of query type
  - type is indirect subtype
  additional tests (phantomMode)
- OTSubTypeHierarchyTest011: bugfix: type is indirect subtype
- OTSubTypeHierarchyTest010: bugfix: type is indirect subtype
- OTSubTypeHierarchyTest006: bugfix: type is indirect subtype (pict. is wrong)
- OTSubTypeHierarchyTest004: bugfix: type is indirect subtype
- OTSubTypeHierarchyTest001: many bugfixes:
  - type is indirect sub via phantom type
  - type is not a subtype of query type
  - type is indirect subtype
  additional test for phantom mode
- CompleteRoleHierarchyWithClasses: several bugfixes:
  - type is not reachable from focusRole
  new tests: use more specific focus type
  
Tests pass except for one regression mentioned already in comment 2
Comment 4 Stephan Herrmann CLA 2010-08-12 16:03:31 EDT
r684, r684 adjust the first refactoring (pushdown) to the new strategy.

Required fixes in OTTypeHierarchies:
- make getRealTSuper() succeed even if allTSupersLinearized is null (below focus)
- support explicit creation of ConnectedPhantomType
- filtering phantoms explicitly replaces ConnectedType with ConnectedPhantomType
Comment 5 Stephan Herrmann CLA 2010-08-13 19:01:41 EDT
Created attachment 176593 [details]
More migration

Migrate more refactorings to the new strategy:
 * pullup, rename type, 

Cleanup:
 * migrate two functions from team PhantomTypeAdaptor to PhantomType
   and remove the team.
 * do not require internal class TypeHierarchy in API methods,
   solved by an abstract super role bound to ITypeHierarchy
 * remove adaptations used for
   - replacing TypeHierarchy with OTTypeHierarchy
   - avoiding getSuperclass calls on OTTypeHierarchy
 * remove obsolete team OTTypeHierarchyAdaptor

Necessary addition in OTTypeHierarchies:
 * new query getAllTSubTypes(TypeHierarchy,IType)
Comment 6 Stephan Herrmann CLA 2010-08-14 12:06:23 EDT
Created attachment 176601 [details]
Still more migration

Cleanup:
* enable classic hierarchy mode (= remove role ViewPart)
* no longer create OTTypeHierarchy
  - remove role LifeCycle
* consume new strategy for superclass linearization, remove these roles:
  - SubTypeHierarchyContentProvider (original getParent() is fine now)
  - JavaModelUtil (original isSuperType() is fine now)
  - MethodOverrideTester
    (original methods are fine: findOverriddenMethod, computeSubstitutions)
  - TraditionalHierarchyContent (original getParentType() is fine now)
* stop prefixing role names with their team, post qualification works OK
  - remove roles HierarchyLabelProvider, MethodsLabelProvider

Enhancement:
* enable F4 (open type hierarchy for method mappings in the outline view)

Minor issue: MethodOverrideTester.computeSubstitutions first calls
IType.getSuperclassSignature and then fHierarchy.getSuperclass(type), 
assuming both refer to the same type, which is not true if type has tsupers.
Not clear what could possibly break here.
Comment 7 Stephan Herrmann CLA 2010-08-14 16:13:48 EDT
Last references to OTTypeHierarchy have been removed from otdt.refactoring:
 * no longer adapt RippleMethodFinder2:
   the adaptation was crippled more than it helps now after the change
 * no longer create OTTypeHierarchy from
   - RenameVirtualMethodProcessor
   - PullUpRefactoringProcessorRole
 this is r697

More plugins have been cleaned up after the strategy change:

- otdt.ui: r696

- otdt.debug.ui: r698 (dependency on objectteams.runtime shouldn't be needed)

- jdt.core: r699 with one addition in otdt r700

- otdt.tests: r701

Three classes in jdt.core used to depend on OTTypeHierarchy 
which is now solved like such:
- MethodPattern.resolveLevelForType() and RoleType.findSuperBaseClass():
  both methods used to call OTTypeHierarchy.getTSuperTypes().
  Instead we now call ITypeHierarchy.getSuperclass() and rely on the
  fact that OTTypeHierarchies adapts this method to yield the full
  superclass linearization.
- OTType.getRoleTypes() used three different queries depending on a
  bitset argument. Only one of three cases is no implemented in OTType,
  relying on a new role in OTTypeHierarchies to intercept and handle
  the other two cases (getTypesToSearchForRoles())
Comment 8 Stephan Herrmann CLA 2010-08-14 19:01:11 EDT
Commits r704 - r706 remove some useless API from OTTypeHierarchies:

* getAllSuperTypes(): instead of providing alternative implementations,
  adapt the original one from TypeHierarchy (supported by a small change
  in TypeHierarchy, as to use getSubclass() for a proper join point).

* getAllSuperclasses() was only chaining through the team (except for
  a check isInterface()).

This alone caused behavior changes which are compensated by
 * also filtering phantoms from getAllSuperTypes()
 * checking isInterface inside getSuperclassLinearized() 
   (based on a new flag remembered from connectTSupers(),
    we can't use isInterface due to in-exists()ing phantom types).

For performance reasons, getSuperclassLinearized has now a
a binding base guard (OTModelManager.isRole()).

Additionally, comments from old OTTypeHierarchy have been transferred
to the new team and were further improved.
Comment 9 Stephan Herrmann CLA 2010-08-14 20:24:28 EDT
Commit r707 - r711 contain the final cleanup:

* remove OTTypeHierarchy* & CopyInheritanceInfo from org.eclipse.jdt.core

* three classes have found their new home in org.eclipse.objectteams.otdt:
  - OTTypeHierarchyTraverser
  - TraverseRequestor
  - InheritedMethodsRequestor
  this implied that two methods from TypeHelper had to be moved out of the core
  they are now in RefactoringUtil.

  I have also slightly simplified the three moved classes:
  - replace HashMap<String,Boolean> with a small record class
  - remove unsupported option "hierarchyToTraverse", only super is implemented
  + also support reuse of a client-provided type hierarchy.

Finally, tests in RefactoringUtilTest have been revived (which were
disabled since the 3.2 migration, I believe)
Comment 10 Stephan Herrmann CLA 2010-08-15 19:37:37 EDT
Regressions in OTSubHierarchyContentProviderTests showed that we were not
correctly handling the following cases:
(A) types that are unrelated to the focus type
(B) filtering/substituting phantom types in subtype hierarchies

Commits r715 - r718 fix these by the following changes:
(A) Fix tsuper-navigation for types unrelated to the focus type:
   don't rely on allTSupersLinearized being set but use directTSupers.
(B) Ensure symmetry between tsub and tsuper navigation: in non-phantom mode
   always try to replace a phantom role with the next non-phantom role(s).
   This is important for capturing roles beyond 'holes' (phantoms) in the
   middle of a hierarchy.
 * when computing subtypes in non-phantom mode replace phantoms with all
   their non-phantom tsubtypes (new method collectRealTSubs())
   TODO: might have to include explicit subtypes, if they are not otherwise
   rooted.
 * avoid that traversals would stop when encountering a phantom role:
  - conditionally filter from addTSubs() only if intercepting a toplevel query
  - no longer intercept getAllSuperclasses, but let getSuperclassLinearized()
    take care of phantoms.

Tests have been adjusted correspondingly:
 * Some indirect tsub roles had been removed from expected results, reverted.
   (OTSubTypeHierarchyTest{001,004,017})
 * OTSubHierarchyContentProviderTests: do expect meaningful answers from
   getParent(), correct expected results and added one more test.

Additionally, one more method in LookupEnvironment is integrated with
Dependencies, as required by RenameTypeTests (tsupers were not correctly
connected).
Comment 11 Stephan Herrmann CLA 2010-09-23 09:46:20 EDT
Verified using I201009211735