To see an example of specifying a framework in Plural, download the MiniEcipse example from Blackboard. It's probably best to focus on MiniEclipseSimple.zip, which just specifies the framework interfaces and verifies a simple client. The framework is supposed to be something like Eclipse, though it is vastly simplified. The client, SimplePlugin.java, creates an instance of itself in main() and passes the instance to the run method of the Main class in the framework. Plugin.java is an interface defining the Plugin lifecycle: Plugins start in the created state, in which start() is called, transitioning the plugin into the started state. Finally stop() is called, transitioning the plugin into the stopped state.
The plugin must be able to interact with the framework, and so a
FrameworkFacade interface is passed to each of the Plugin lifecycle
callbacks. The FrameworkFacade can itself be in one of three
states: setup (which is when Plugin.start() is called), running, and
teardown (which is when Plugin.stop() is called). The Plugin
methods are specified to take a FrameworkFacade interface in one of
these states. Our SimplePlugin registers a menu and associates it
with an Action. Note that it must do this in start() because the
registerMenu() method in FrameworkFacade requires the FrameworkFacade
to be in the "setup" state. This shows how typestates can
constrain the plugin to only call methods that are appropriate in a
particular lifecycle callback.
One technical side note: any method implementation that, like
SimplePlugin.start(), changes the state of the object (in this case
from created to started) must be declared with a permission where
fieldAccess=true. The idea is that you transition from one state
to another by making some changes to the object's fields. Of
course occasionally you don't actually have to change the fields, but
Plural still requires this annotation, so put it in. It is NOT
necessary in interfaces, because they do not contain method
implementations. If you are using @Perm instead of @Full or
similar, you must specify a permission on this with "this!fr", where
the !fr is the string-based syntax for fieldAccess=true. Note
that this will NOT affect you if all you are doing is specifying
interfaces; however, as soon as you check real code (even blank method
bodies) with Plural, you'll have to pay attention to this.
If you want to specify in a precondition or postcondition that an
argument or result is not null, use the @Perm permission and say #0 !=
null. Here #0 refers to the first argument; you can use #1 for
the second method argument, etc., or this for the receiver or result
for the result. Here's an example:
@Perm(requires = "#0 != null", ensures = "result != null")
public Object identity(Object o) {
return o;
}