Contributing a clean up and a save action using the clean up extension point

The org.eclipse.jdt.ui.cleanUps extension point enables you to contribute your own Java code clean ups and Java editor save actions. Clean ups help in resolving problems in a compilation unit or establishing a code style. A save action is a special clean up that perform the requested modifications on save automatically.

Using the extension point

To create a new extension for the org.eclipse.jdt.ui.cleanUps extension point you need to first provide the required extensions in the plugin.xml. There are 3 extensions that need to be declared as shown below with the example of a clean up which updates the copyrights for a file on save:

   <extension
         point="org.eclipse.jdt.ui.cleanUps">
      <cleanUp
            id="org.eclipse.jdt.copyrightsaveaction.copyright_clean_up"
            class="org.eclipse.jdt.ui.internal.copyrightupdater.CopyrightUpdaterCleanUp">
      </cleanUp>
      
      <cleanUpOptionsInitializer
            class="org.eclipse.jdt.ui.internal.copyrightupdater.CopyrightOnSaveOptionsInitializer"
            cleanUpKind="saveAction">
      </cleanUpOptionsInitializer>
      
      <cleanUpConfigurationUI
            class="org.eclipse.jdt.ui.internal.copyrightupdater.CopyrightTabPage"
            name="%cleanUpConfigurationUI.name"
            cleanUpKind="saveAction">
      </cleanUpConfigurationUI>
   </extension>

For a description of the individual attributes, please refer to the extension point documentation.

Contributing a clean up

To contribute a clean up, you need to first create the class that implements the ICleanUp Interface. Lets create the CopyrightUpdaterCleanUp class for our example clean up and implement the inherited methods:

	public class CopyrightUpdaterCleanUp implements ICleanUp {

		private CleanUpOptions fOptions;
		private RefactoringStatus fStatus;

		public CopyrightUpdaterCleanUp() {
		}
	}
The CleanUpRequirements contain various requirements for the clean up such as an AST or a fresh AST containing changes from other clean ups, compiler options and changed regions, which are used by the CleanUpContext to create the fix. It has to be returned from the method getRequirements():
	public CleanUpRequirements getRequirements() {
		boolean changedRegionsRequired= false;
		Map compilerOptions= null;
		boolean isUpdateCopyrights= fOptions.isEnabled("cleanup.update_copyrights");//$NON-NLS-1$
		return new CleanUpRequirements(isUpdateCopyrights, isUpdateCopyrights, changedRegionsRequired, compilerOptions);     
	}
A human readable description should be returned for each step of the clean up that is enabled in the current options:
	public String[] getStepDescriptions() {
		if (fOptions.isEnabled("cleanup.update_copyrights"))//$NON-NLS-1$
			return new String[] {"Update Copyrights"};//$NON-NLS-1$

		return null;
	}
The CleanUpOptions for the supported options keys will be set using setOptions(...):
	public void setOptions(CleanUpOptions options) {
		Assert.isLegal(options != null);
		Assert.isTrue(fOptions == null);
		fOptions= options;  
	}
The clean up pre-conditions and post-conditions are being checked in checkPreConditions(...) and checkPostConditions(...):
	public RefactoringStatus checkPreConditions(IJavaProject project, ICompilationUnit[] compilationUnits, IProgressMonitor monitor) throws CoreException {
		if (fOptions.isEnabled("cleanup.update_copyrights")) { //$NON-NLS-1$
			fStatus= new RefactoringStatus();
		}
		return new RefactoringStatus();
	}
	public RefactoringStatus checkPostConditions(IProgressMonitor monitor) throws CoreException {
		try {
			if (fStatus == null || fStatus.isOK()) {
				return new RefactoringStatus();
			} else {
				return fStatus;
			}
		} finally {
			fStatus= null;
		}
	}
Finally, a ICleanUpFix is to be created which fixes all the problems for the given context using createFix(...)
	public ICleanUpFix createFix(CleanUpContext context) throws CoreException {
		CompilationUnit compilationUnit= context.getAST();
		if (compilationUnit == null)
			return null;

		return CopyrightsFix.createCleanUp(compilationUnit, fOptions.isEnabled("cleanup.update_copyrights"));//$NON-NLS-1$
	}

Contributing a clean up options provider

To create the UI for the clean up, an options provider tab page has to be created by implementing the ICleanUpConfigurationUI interface. The page can be created by implementing the createContents(...) method in the CopyrightTabPage class. The preferences page along with the desired groups and options can be created using the method doCreatePreferences(). Optionally, a code snippet of the new clean up with the given options can be shown in the clean up preview tab using the method getPreview(). If the CleanUpOptions get modified in the UI, they need to be set again using the method setOptions(...).

Contributing a clean up options initializer

A clean up options initializer, which returns the default options for each clean up kind can be created by implementing the ICleanUpOptionsInitializer. The options initializer can either be contributed for a normal code clean up or for a save action.

	public class CopyrightOnSaveOptionsInitializer implements ICleanUpOptionsInitializer {

		public CopyrightOnSaveOptionsInitializer() {
		}

The default options for this initializer can be set in setDefaultOptions(...)

	public void setDefaultOptions(CleanUpOptions options) {
		options.setOption("cleanup.update_copyrights", CleanUpOptions.TRUE);
	}
}

The UI code to configure the options for this example can be found here: CleanUpTabPage.java.