New & Noteworthy for Handly 0.5
Handly is breaking new ground with the 0.5 release, a true "2.0" version in spirit. Many of the core APIs have been revised in this release to make Handly even more flexible and robust.
Due to the API rework involved, this release introduces a number of breaking changes and is expected to be more disruptive than previous releases. Please see the migration guide if you are a current adopter.
Please note that the minimum requirements have changed in this release. Previously, Eclipse Juno (3.8) and Java 6 were sufficient. Handly 0.5 requires at least Eclipse Luna (4.4) and Java 8 (bug 474391, bug 487996).
Here are the highlights of this release.
New Design for the Model API
The 0.5 release introduces an entirely new design that gives the implementor of a Handly-based model complete control over the model API (bug 491564). Among other things, this should make it possible to use Handly for (re-)implementing handle-based models where the model API is a given, just as in the case of a preexisting model API that needs to be preserved for backward compatibility.
In the new design, IElement, ISourceElement, ISourceFile, ISourceConstruct, and IElementDelta are just marker interfaces. Implementors of these marker interfaces must also implement the corresponding "implementation interfaces" IElementImpl, ISourceElementImpl, ISourceFileImpl, ISourceConstructImpl, and IElementDeltaImpl, which follow a specific convention of prefixing the method names with h (such as hName(), hParent(), etc.). The base classes Element, SourceElement, SourceFile, SourceConstruct, and ElementDelta provide a default implementation of these interfaces and also follow the h-prefix naming convention for the non-static API methods (public or protected).
Such design effectively separates generic, "meta-level" methods defined by the framework from model-specific, "base-level" methods defined by the model implementor. It significantly reduces the possibility of a method conflict in the inheritance hierarchy and gives the model implementor a lot of freedom with regard to the model’s base-level API.
The classes Elements and ElementDeltas provide static methods for generic access to elements and element deltas, such as Elements#getName(IElement) and ElementDeltas#getElement(IElementDelta). Usually, those methods just cast their first parameter to the corresponding "implementation interface", and call an appropriate method of that interface. Together with the common "marker interfaces", these classes form a uniform meta-level API that establishes a common language and makes it possible to work in a generic way with any Handly-based model. It should be noted that this "reflection facility" is intended to be used primarily by "generic clients" such as common UI components; "ordinary clients" will typically use the base-level API of a concrete model and thus are not exposed to the somewhat increased syntactic verbosity of calling static methods in Java.
When defining the model’s base-level API the model implementor can, for the sake of convenience, extend model-specific interfaces from one or more of the relevant "extension interfaces" IElementExtension, ISourceElementExtension, ISourceFileExtension, and IElementDeltaExtension. These interfaces effectively act like mix-ins and define default methods that delegate to corresponding methods of the classes Elements and ElementDeltas. For example, IElementExtension#getName() calls Elements.getName(this) and IElementDeltaExtension#getElement() calls ElementDeltas.getElement(this). The implementor always retains control over picking and choosing desirable extensions and over the model’s base-level API as a whole. In particular, model-specific interfaces are not required to extend any framework interfaces.
Consider IFooElement, a model-specific interface that represents an element of a handle-based Foo Model, which is going to be implemented with Handly. The framework allows the following three alternatives for IFooElement:
- IFooElement doesn’t extend a framework interface. This is relevant if you are unwilling to have any dependency on Handly in your model API or if IFooElement is a preexisting interface outside your control.
Note that it is usually a good idea to extend model-specific interfaces from the relevant common interfaces such as IElement in order to make the model easier to use with APIs expressed in terms of the common interfaces. Otherwise, explicit casts might be necessary when interacting with such APIs. (An important example of such API is the class Elements mentioned above.) This is why the other alternatives are generally preferable to this one.
- IFooElement extends the marker interface IElement (only). This is relevant if you can tolerate a dependency on Handly in your API but would like to define the model API "from scratch" or have already defined the API and need to maintain compatibility with existing client code.
- IFooElement extends IElementExtension (and, hence, IElement) and thus inherits a number of predefined methods. This is similar to what has been available since Handly 0.1 and is in fact the recommended approach when migrating to Handly 0.5 from a prior release.
Optional Dependency on org.eclipse.core.resources
The Handly core framework (the org.eclipse.handly bundle) as a whole no longer has a mandatory dependency on org.eclipse.core.resources (bug 488819). Together with the new design for the model API discussed above, this is intended to expand the project’s applicability. Note that some of the implementation classes provided by the core framework (such as SourceFile) still require the workspace. Future releases may further reduce the dependency on org.eclipse.core.resources. However, support for models built on top of the Eclipse workspace remains a priority.
Other API Enhancements
- A number of previously deprecated API elements have been removed in this release (bug 487183)
- Some of the model-related API elements have undergone a refactoring (bug 491568, bug 491647, bug 491649)
- A better design for the working copy facility has been implemented (bug 492179)
- Any Object can now be used as an Element body (bug 491570)
- The buffers are now compatible with the try-with-resources construct, taking advantage of Java 7 (bug 476988).
In addition, several new APIs have been introduced in this release:
- The class ElementDelta.Builder helps build a delta tree (bug 491575)
- The class EditorUtility provides common methods for finding an open editor for a given element and revealing an element in an editor (bug 488547)
- The package org.eclipse.handly.ui.navigator contains reusable components for the Common Navigator Framework such as LinkHelper and OpenActionProvider (bug 488548).
Enhancements in Xtext Integration
This release supports Xtext 2.10 (along with Xtext 2.9 and 2.8).
Also, advanced support for clones of the Xtext Editor has been implemented (bug 488560).
Enhancements in the Java Model Example
- Example Java navigator view (kindly contributed by Ondrej Ilcik, Codasip);
- Example Java editor, with Handly-based reconciling and outline.
To try it out, open the 'Java Navigator (Handly)' view (under the 'Handly Examples' category). The view shows the elements of the example Java model. You can navigate the structure of the projects in your workspace down to types, methods, and fields in Java source files. Select a Java file and edit it with the 'Java Editor (Handly Java Model Example)'. Notice that changes to the inner structure of the source file are reflected in both the Java Navigator and the Outline view.
Please note that the UI functionality is necessarily very much contrived. In particular, the example Java editor is based on a simple text editor with no syntax coloring, content assist, or reporting problems as you type. The goal has been to keep the example code comprehensible while demonstrating the relevant Handly-related functionality such as reconciling and outline. Similarly, the limitations of the example model are revealed in earnest in the Java Navigator view. Also, the view provides no actions for manipulating the model – you can use the standard Package Explorer for that – but changes in the underlying model will, of course, be reflected in the view.
Besides the addition of the UI parts, the example model itself has been updated in this release (bug 492267) to take advantage of the new design for the model API presented above. The interfaces for Java elements now define the element API "from scratch" and extend only common "marker interfaces" while IJavaElementDelta mixes in the predefined default methods from IElementDeltaExtension and the predefined constants from IElementDeltaConstants. This demonstrates the flexibility the model implementor now has when defining the model API.
The architectural overview has been thoroughly revised to reflect the new design introduced in this release. Also, the content of the project’s web page has been restructured and updated thanks to the feedback kindly provided by Vlad Dumitrescu, of erlide fame.
There is no better way to evaluate a framework than seeing how others have used it in real world projects. With that in mind, a wiki page has been created to highlight adopters of Handly and how they are using the framework.
Our early adopters have kindly shared two success stories describing how Codasip Studio and 1C:Enterprise Development Tools are using Handly.
If you are a current adopter, please consider contributing a section. You can promote your product or project a bit while benefiting others in the process.