Table of Contents
Code Recommenders uses an event bus to get rid of all kind of listener interfaces. Although considered to be used internally mostly, the bus may be used by other subscribers (such as usage data collectors, indexing services etc.) to respond to events such as compilation unit changes, project creations or deletions etc.
To subscribe to the event bus one has to obtain an instance of
EventBus
using Code Recommenders' injection service (or Guice Injector).
Event providers using the workspace event bus:
JavaElementEventsProvider
: a provider that sends events such as project open/close or compilation unit
added/removed/changed/saved events. See
the section called “JavaElement Events Provider”
for more details on this provider.
Code Recommenders offers an AST caching service that can be used by completion engines to get the last know ast of a compilation unit.
Do we still need that? Why not use the AST that is send with the compilation unit?
The
JavaElementEventsProvider
sends events such as project open/close or compilation unit added/removed/changed/saved events. This list
is incomplete and is expected to grow quickly for 1.0. Look at the corresponding class to learn which events it
posts to the event bus.
This example briefly illustrates the graph structure used to create call chains by a simple example:
ExecutorService pool = Executors.newCachedThreadPool(); Future future = $
Class Responsibilities
CallChainCompletionProposalComputer
: Extracts the available information about accessible locals, fields and methods to find all
potential entry-points for the
GraphBuilder
.
CallChainCompletionProposal
: The proposal that gets executed when the user selects the proposal from code completion
window. It internally relies on a (jdt)
Template
built by the
CompletionTemplateBuilder
.
CompletionTemplateBuilder
: builds, as the name suggests, the Java template. It does quite a lot JDT internal magic and is
considered unclean and yet incomplete (!).
GraphBuilder
: Creates the call chain graph. Uses a thread pool internally for building the graph (but not
for creating the call chains). This might change?
TypeNode
: represents the class node in a call chain. It stores the incoming edges which are later used
to travers the graph and build the call chains.
MemberEdge
: represents a transition from one type to another, typically an IMethod, IType, or
ILocalVariable (for entry points only).
Class Responsibilities
central controller; manages the registering and unregistering of
all components on the
EventBus
;
listens for selection events and delegates them to the
ProviderExecutionScheduler
. Uses
ProviderConfigurationPersistenceService
to persist the width of the
Sash
(vertical separator between overview and content).
Manages the subscriptions for specific java selections of all
registered providers.
Can be queried to return a matching
java.lang.reflect.Method
for a given provider that should be called for the selection. No
guarantees are provided
which method is returned if multiple
methods of a provider overlap.
Manages the multithreaded execution of all providers. To indicate
the status of
the execution corresponding execution events are
posted to the
EventBus
.
Extdoc providers are the entities of the extdoc view that bring
the real content. Providers are registered via the extension point
org.eclipse.recommenders.extdoc.rcp.provider
.
The content is provided through methods that are annotated with a
@JavaSelectionSubscriber
annotation. More details on
this and an example provider is given
in a
later section
ExtdocProvider
provide an
ExtdocProviderDescriptor
to access their
A single
List<ExtdocProvider>
is injected to all entities that need to know the providers.
darstellung des status aktivierung / deaktivierung order change insb. das management in der liste
manages the displayed content. A new (background) rendering
panel
can be created and the corresponding
Composite
can be accessed for each provider.
Helper class for the visualization of the providers. Mainly
accessed by the
ProviderContentPart
it can be used to set a status or to show the contents of
a
provider when it is completely rendered.
This entity is left out in the diagram. It is registered on the
EventBus
and used to persist the provider configuration to disc on change.
The provider configuration consists of the order of all providers
and of a list of all disabled providers.
This entity is left out in the diagram. It directly accesses Eclipses singletons to be able to load and save preferences. A low-level API is provided to load/store:
order of the providers
disabled providers
position of the sash in the Extdoc view
This entity is mainly used to increase the testability of all entities that make use of it as they do not need to access Eclipses singletons and this class can be exchanged with a mock for testing.
A
JavaSelectionEvent
is posted to the extdoc view.
A new
ProviderExecutionScheduler
is created and the old one is disposed.
The
SubscriptionManager
is used to identify the providers that are interested in the
selection.
A new (hidden) rendering panel is created in the
ProviderContentPart
.
For each provider the new content area is requested and used as a
parameter for the provider execution. This is done by the
ProviderExecutionScheduler
in multiple threads.
The
ProviderOverviewPart
updates the provider icons according to the posted execution events
of all providers.
The
ProviderContentPart
listen for the resulting events and update their displayed data
accordingly. On finish events the hidden content area of the
provider is shown, delay and fail events lead to a status message.
The
ProviderContentPart
listens for the
RenderNowEvent
and switches the rendering panel to the new foreground panel if it
is posted.
This example is a conceptual view onto the events that are posted during the provider execution. For this example it is assumed that three providers are registered:
P1 is a fast provider that terminates correctly.
P2 is a provider that crashes on execution with an exception.
P3 is a provider that terminates correctly but takes very long.
The entry point is the
schedule(selection)
call from the extdoc view. The current selection is provided as a
parameter and a
NewSelectionEvent
is posted. Based on the selection
all subscribed provider methods are
queried from the
SubscriptionManager
. A
ProviderStartedEvent
is posted for each provider and the execution is started in separate
threads. Additionally a timeout is started to be able to guarantee a
maximum rendering time for the Extdoc view.
P1 finishes first and the successful execution triggers the posting
of a
ProiderFinishedEvent
. The event contains the corresponding provider. P2 crashes on
execution and the caught exception triggers a
ProviderFailedEvent
. Also P3 is not finished yet the render timeout is reached so the
next event is a
RenderNowEvent
companied by
ProviderDelayedEvent
s for all still running providers.
. P3 terminaes successfully after
this and a
ProviderFinishedLateEvent
is posted.
In addition to the normal execution events it is possible that a provider is not interested in a selection. This is possible in two different ways:
If a provider is not subscribed to a selection the
SubscriptionManager
does not find a suitable method.
A provider might detect during the execution that no data is
available to successfully process the selection. In this case a
Status.NOT_AVAILABLE
can be returned.
In both cases a
ProviderNotAvailableEvent
is posted for the provider.
Several other events exist:
ProviderOrderChangedEvent
: indicates a reordering of the providers
ProviderDe-/ActivationEvent
: posted if providers are enabled/disabled. Both are consumed by
the
ProviderExecutionScheduler
. Activation events lead to the execution of the provider with the
last selection, deactivation events cancel the running provider.
ProviderSelectionEvent
: if providers are selected in the overview the content shuld
"jump" to their positions in the content. This event is
used to indicate such a selection and is irrelevant for the
execution scheduler.
All these are posted from the UI components and not from the scheduler.
Description of the Layout
ExtdocView
: Central view that is registered with Eclipse and container for
all sub content parts.
ProviderOverviewPart
: Manages an overview of all available Extdoc providers in a table.
Each provider can be de-/activated by un-/checking the associated
ProviderItem
. The order of the providers can be changed through drag and drop.
ProviderContentPart
: Manages a scrolling stack of content panes. Allows to create a
new (background) rendering
Composite
that contains
ProviderArea
s for all providers.
The
ProviderContentPart
is registered on the
EventBus
and subscribes all provider related events.
Depending on the
execution status a providers area is shown or the status is set.
ContentPane (Composite)
simple composite that contains all rendered content for a selection
ProviderArea
: area that is associated with an Extdoc provider. Allows to set an
(optionally clickable) status and to show the rendered content.
All
sub elements are plain SWT components and with the exception of the
content that is provided to the
ExtdocProvider
all are hidden to the outside. Renders a title for the associated
provider.
TitleArea (Composite)
status for a providers. It is used at the moment to show delay in
execution or to show execution failures.
StatusArea (Composite)
status for a providers. It is used at the moment to show delay in
execution or to show execution failures.
ContentArea (Composite)
Composite that contains the rendered results of the corresponding
provider.
An
ExtdocProvider
is registered on the
SubscriptionManager
.
To be recognized as an provider its methods need to be annotated
with a
JavaSelectionSubsriber
annotation. The parameter list of such methods is fixed:
a
IJavaElement
(or a subclass of it)
defines for which elements this methods
provides some content.
the fired
JavaSelectionEvent
a
Composite
into which the contents should be rendered
Three examples are shown in the following diagram.
The simplest case is shown in the method
example(...)
. The annotation indicates that it is interested in all
JavaSelectionEvents
. Because the first parameter is an
IJavaElement
(the super class of all selectable java elements) the method is
executed for all possible events.
It is possible to use the annotation and the
IJavaElement
as a filter
to be able to write more specialized provider methods. An
example of this is given in method
unavailableProvider(...)
.
The annotation take optional arguments to specify locations for
which a selection should be processed.
It is possible to provide
multiple locations, i.e.:
@JavaSelectionSubscriber({METHOD_BODY, TYPE_DECLARATION})
.
The events are also matched by the selected java element so it is
possible to only subscribe for
IType
selections if it is used as the first parameter.
Word of caution: if method subscriptions overlap (like it is in this example) only on method is called on an event. No guarantees are given which one.
The providers are executed in their own thread so it is
necessary to
switch to the UI thread for the rendering.
Take a look on the two
parts of the
example(...)
method.
All non-UI related information gathering should be done in the
provider thread.
After that a
Runnable
can be executed with the helper method
runSyncInUiThread(...)
. By doing so exceptions that are thrown in the runnable are bubbled
out of the
Runnable
and rethrown in the provider thread.
The execution is run sync so that
the providers does not finish until the rendering is complete.
A provider can return an
ExtdocProvider.Status
to indicate its processing status.
A normal execution returns
Status.OK
.
If it is not possible to process the current selection (i.e. because
the provider has no data available), it is possible to return
Status.NOT_AVAILABLE
.
The provider status is then handled by the UI as if it is not
subscribed even if it has already started processing.
It is feasible to throw an exception in a provider as shown in method
errorCase(...)
.
In this case the provider is shown as failed in the UI and a link is
shown that opens a dialog with a stacktrace and the message from the
exception.