Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement project configurator API #326

Closed
donat opened this issue Feb 7, 2017 · 0 comments
Closed

Implement project configurator API #326

donat opened this issue Feb 7, 2017 · 0 comments

Comments

@donat
Copy link
Contributor

donat commented Feb 7, 2017

Overview

External plugins want to hook into the Buildship project synchronization process. For example, the Spring Tool Suite wants to ensure that all Spring projects using Gradle have the Spring nature Associated. Also, external tooling providers can investigate the Gradle build and add arbitrary configuration during the synchronization.

Design

Buildship should provide an extension mechanism for the Gradle project synchronization. The implementation should use the traditional extension point mechanism, just like in m2e (see m2e schema, and interface). The interface should provide a way to configure projects one-by-one with the possibility to unconfigure projects, should they be excluded from the build.

The existing project synchronization should be refactored into project configurators. There should be a separate configurator for setting the project metadata and another one for setting the JDT metadata.

Implementation

Extension point

External plugins should declare project configurators via the org.eclipse.buildship.configurators extension point. The schema should define the following attributes:

  • name*: Identifies the configurator within the contributor plugin.
  • displayName*: Human-readable name used on the UI.
  • class*: The fqn of the class implementing the project configurator. The target must implement the GradleProjectConfigurator interface.
  • runsBefore: Defines ordering between configurators. The value should be a comma-separated lists referencing other configurators with their unique IDs. A unique ID is calculated with the <plugin_id>.<configurator_name> pattern.
  • runsAfter: same as runsBefore, but with reversed precedence.

* marks the required attributes.

Interface

The extension point should point to a ProjectConfigurator implementation. During each project synchronizations, the project configurators are created once. Before the the synchronization begins the init() method is called. Then, the configure() method is invoked for each project in the Gradle build. For the projects that are removed from the Gradle build the unconfigure() method is called.

The configurators are expected to report progress and check for cancellation via the progress monitor argument.

The project synchronization should continue the execution even if a configurator throws an exception.

interface ProjectConfigurator {
    void init(InitializationContext context, IProgressMonitor monitor)
    void configure(ProjectContext context, IProgressMonitor monitor)
    void unconfigure(ProjectContext context, IProgressMonitor monitor)
}

During the initialization the InitializationContext is available for the configurator to prepare for the execution. This is usable when - for instance - the configurator needs to load extra information from the Gradle build (see #726).

interface InitializationContext {
    GradleBuild getGradleBuild()
}

A ProjectContext instance is passed to both the configure() and unconfigure() methods in order to obtain the reference to the workspace project being configured.

interface ProjectContext {
    IProject getProject()
}

Test coverage

  • Normal behavior
    • When a project configurator is declared then it becomes part of the synchronization.
    • When multiple project configurators are declared then they are executed during the synchronization.
  • Exceptional behavior
    • When a project configurator throws an exception then the synchronization continues uninterruptedly.
  • Ordering
    • When no order is declared then configurators should be executed in an undefined but stable order (always the same order for the same configurators).
    • When a runsAfter or runsBefore is declared, then the execution order must be respected:
ConditionExpected order
A runsAfter BB, A
A runsBefore BA, B
A runsAfter B, B runsAfter CC, B, A
  • When a configurator has an unknown configurator specified in runsAfter or runsBefore then the condition is ignored.
  • When configurator A runsBefore A or runsAfter A then it should be omitted from the synchronization.
  • When a configurator introduces a cycle in the ordering then it should be omitted from the synchronization.
  • Cancellation
    • When the synchronization is canceled then the currently running configurator is notified via its progress monitor.
    • When the synchronization is canceled then only the currently running configurator can finish and the subsequent configurators are not executed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant