New & Noteworthy for Eclipse Handly 0.7
Almost all of the issues targeted by Eclipse Handly 0.7 release are concerned with Core API quality. The 0.7 development has been informed in a large part by trying to adopt Handly within the context of a non-trivial existing model implementation (namely, an experimental fork of Eclipse Java development tools) to ensure that Handly can deliver a solid foundation without affecting any of the public APIs (and most of the internal APIs) of the existing model.
Due to the API rework involved, this release introduces a number of breaking changes. Please see the migration guide if you are a current adopter.
Here are the highlights of this release.
Introducing *ImplExtension and *ImplSupport Interfaces for Elements
The new design introduced in Handly 0.5 has defined a number of *Impl interfaces which need to be implemented by elements of any Handly-based model. Although it is perfectly fine for elements to implement *Impl interfaces directly, Handly has provided a hierarchy of skeletal implementation classes (rooted in the class Element) that elements can extend to minimize the effort required to implement these interfaces. However, that class-based approach has had a number of limitations, which this release attempts to address by introducing additional *ImplExtension and *ImplSupport interfaces for elements.
*ImplExtension Interfaces (515461)
Besides partially implementing corresponding *Impl interfaces, skeletal implementation classes have effectively defined an "extended" API of their own. A few important auxiliary classes provided by Handly, such as ElementCache, ElementDifferencer, ElementManager, and StructureHelper, have come to depend on some parts of that API. This meant that these auxiliary classes could only work with elements which extended skeletal implementation classes. That was unnecessarily restrictive.
To eliminate this dependency of auxiliary classes on skeletal implementations, this release extracts appropriate parts of the extended API of skeletal implementation classes to the new *ImplExtension interfaces that auxiliary classes and other clients can depend on and that may be implemented by elements directly if the need arises.
*ImplSupport Interfaces (515667)
Single inheritance might not be expressive enough to allow the implementor to factor out all the common features shared by elements of a specific model while using skeletal implementation classes provided by Handly. For example, the implementor could factor out the common features of Java elements into the class JavaElement, which would extend Element. However, the class CompilationUnit would then need to extend both JavaElement and SourceFile, which is not possible with single inheritance. There are workarounds, such as explicitly duplicating features from JavaElement in CompilationUnit, or introducing an internal "trait-like" interface with default methods (say, IJavaElementInternal) in place of or in addition to the class JavaElement. However, our experience with the Java model of Eclipse Java development tools has shown that such workarounds can be quite constraining for the implementor of a real-world, non-trivial model.
This release attempts to provide skeletal implementations for *Impl and *ImplExtension interfaces in a more flexible way by introducing additional "trait-like" *ImplSupport interfaces with default methods extracted from corresponding skeletal implementations in the Element hierarchy. The new approach enables a form of multiple inheritance of behavior. Model implementors may "mix in" *ImplSupport interfaces directly or extend classes in the Element hierarchy, as they see fit. For example, the class JavaElement could just extend Element, while the class CompilationUnit could extend JavaElement and implement ("mix in") ISourceFileImplSupport.
Other API Enhancements
- New API methods have been introduced in ElementDelta and ElementDifferencer to make them more flexible for subclassing (514798, 514848)
- Element closing API has been revised (515099)
- Any IElement is now allowed as Element's parent (515232)
- An earlier API mistake has been fixed by introducing a separate hBuildSourceStructure method that source files now need to implement instead of hBuildStructure (515246)
- New API methods have been introduced to make equals implementation in elements more flexible (515302, 517614)