diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..8a8f166 --- /dev/null +++ b/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..7ded55f --- /dev/null +++ b/.project @@ -0,0 +1,34 @@ + + + lombok.eclipseplugin + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.api.tools.apiAnalysisBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.pde.api.tools.apiAnalysisNature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..54e493c --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000..70f5f6d --- /dev/null +++ b/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.ui.text.custom_code_templates= diff --git a/AUTHORS b/AUTHORS index 9b8fae7..b12c07e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,5 +1,6 @@ Lombok.eclipseplugin contributors: Reinier Zwitserloot +Rabea Gransberger By adding your name to this list, you grant full and irrevocable copyright and patent indemnity to Project Lombok and all use of Project Lombok, and you certify that you have the right to do so for all commits you add to Project Lombok. diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF new file mode 100644 index 0000000..5489791 --- /dev/null +++ b/META-INF/MANIFEST.MF @@ -0,0 +1,19 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: lombok.eclipse;singleton:=true +Bundle-Version: 0.11.0.qualifier +Bundle-ActivationPolicy: lazy +Bundle-Activator: lombok.eclipse.internal.LombokEclipsePlugin +Require-Bundle: org.eclipse.ui, + org.eclipse.core.runtime, + org.eclipse.core.resources, + org.eclipse.jdt;bundle-version="3.6.0", + org.eclipse.jdt.core, + org.eclipse.jdt.core.manipulation, + org.eclipse.jdt.ui, + org.eclipse.text, + org.eclipse.ltk.core.refactoring, + org.eclipse.ltk.ui.refactoring +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 + diff --git a/OSGI-INF/l10n/bundle.properties b/OSGI-INF/l10n/bundle.properties new file mode 100644 index 0000000..febad74 --- /dev/null +++ b/OSGI-INF/l10n/bundle.properties @@ -0,0 +1,3 @@ +#Properties file for lombok.eclipse +Bundle-Name = Lombok Eclipse Plugin +refactor.action.label = Use Lombok Annotations... \ No newline at end of file diff --git a/README.markdown b/README.markdown index ff22dc3..4197d33 100644 --- a/README.markdown +++ b/README.markdown @@ -1,8 +1,11 @@ Eclipse plugin for [Project Lombok](http://projectlombok.org) +Currently provides refactoring for simple getters and setters to Lombok Annotations. + build instructions: -`ant eclipse` +Import the project from this repository as Plug-In Project into Eclipse. -then import the directory as a project into eclipse. +Export from the Overview-Tab of the plugin.xml file and drop the exported file +into your Eclipse application or choose 'Launch an Eclipse application' for testing. diff --git a/articles.txt b/articles.txt new file mode 100644 index 0000000..b83efc5 --- /dev/null +++ b/articles.txt @@ -0,0 +1,2 @@ +http://www.eclipse.org/articles/article.php?file=Article-Unleashing-the-Power-of-Refactoring/index.html +http://wiki.fernuni-hagen.de/eclipse/index.php/Eigenes_Refactoring-Tool_f%C3%BCr_Eclipse_schreiben \ No newline at end of file diff --git a/build.properties b/build.properties new file mode 100644 index 0000000..4dd3ee0 --- /dev/null +++ b/build.properties @@ -0,0 +1,8 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + OSGI-INF/l10n/bundle.properties,\ + OSGI-INF/ + diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..6322de4 --- /dev/null +++ b/plugin.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + diff --git a/src/lombok/eclipse/actions/LombokRefactorAction.java b/src/lombok/eclipse/actions/LombokRefactorAction.java new file mode 100644 index 0000000..9967748 --- /dev/null +++ b/src/lombok/eclipse/actions/LombokRefactorAction.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2009 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.eclipse.actions; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import lombok.eclipse.i18n.Messages; +import lombok.eclipse.internal.LombokEclipsePlugin.Logger; +import lombok.eclipse.refactoring.LombokRefactoring; +import lombok.eclipse.refactoring.LombokRefactoringDescriptor; +import lombok.eclipse.refactoring.RefactoringElement; +import lombok.eclipse.wizards.LombokRefactoringWizard; + +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ltk.ui.refactoring.RefactoringWizard; +import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IObjectActionDelegate; +import org.eclipse.ui.IWorkbenchPart; + +public class LombokRefactorAction implements IObjectActionDelegate { + + private IWorkbenchPart activePart; + private final List elements = new ArrayList(); + + public void dispose() { + // Do nothing + } + + @Override + public void run(IAction action) { + if (!this.elements.isEmpty()) { + LombokRefactoringDescriptor descriptor = new LombokRefactoringDescriptor(); + descriptor.getArguments().setElements(this.elements); + LombokRefactoring refactoring = new LombokRefactoring(descriptor); + run(new LombokRefactoringWizard(refactoring), this.activePart.getSite().getShell(), + Messages.LombokRefactorAction_wizard_title); + } + } + + public void run(RefactoringWizard wizard, Shell parent, String failedCheckDialogTitle) { + try { + RefactoringWizardOpenOperation operation = new RefactoringWizardOpenOperation(wizard); + operation.run(parent, failedCheckDialogTitle); + } catch (InterruptedException exception) { + // if the initial condition checking got canceled by the user. + // do nothing, just return + } + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + this.elements.clear(); + if (selection instanceof IStructuredSelection) { + IStructuredSelection extended = (IStructuredSelection) selection; + for (Iterator it = extended.iterator(); it.hasNext();) { + Object o = it.next(); + checkAndAddSelectedElement(o); + } + } + action.setEnabled(!this.elements.isEmpty()); + } + + @Override + public void setActivePart(IAction action, IWorkbenchPart activePart) { + this.activePart = activePart; + } + + private void checkAndAddSelectedElement(Object o) { + RefactoringElement element = isSupportedElement(o); + if (element != null) { + this.elements.add(element); + } else { + Logger.warn(MessageFormat.format(Messages.LombokRefactorAction_unsupported_element, o.getClass().getName())); + } + } + + private RefactoringElement isSupportedElement(Object o) { + if (o instanceof IJavaElement) { + RefactoringElement supported = RefactoringElement.Factory.create((IJavaElement) o); + return supported; + } else { + return null; + } + } +} diff --git a/src/lombok/eclipse/i18n/Messages.java b/src/lombok/eclipse/i18n/Messages.java new file mode 100644 index 0000000..58f5be6 --- /dev/null +++ b/src/lombok/eclipse/i18n/Messages.java @@ -0,0 +1,47 @@ +package lombok.eclipse.i18n; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + private static final String BUNDLE_NAME = "lombok.eclipse.i18n.messages"; //$NON-NLS-1$ + public static String LombokRefactorAction_unsupported_element; + public static String LombokRefactorAction_wizard_title; + public static String LombokRefactoringWizard_title; + public static String LombokRefactoringWizardPage_equals_hashcode_check; + public static String LombokRefactoringWizardPage_getter_check; + public static String LombokRefactoringWizardPage_message; + public static String LombokRefactoringWizardPage_setter_check; + public static String LombokRefactoringWizardPage_tostring_check; + public static String LombokRefactoring_change_comment_element; + public static String LombokRefactoring_change_comment_elements_title; + public static String LombokRefactoring_change_comment_equals_hashcode; + public static String LombokRefactoring_change_comment_getter; + public static String LombokRefactoring_change_comment_project; + public static String LombokRefactoring_change_comment_setter; + public static String LombokRefactoring_change_comment_tostring; + public static String LombokRefactoring_change_description; + public static String LombokRefactoring_create_change_monitor_begin; + public static String LombokRefactoring_final_condition_monitor_begin; + public static String LombokRefactoring_initial_condition_monitor_begin; + public static String LombokRefactoring_more_than_one_project; + public static String LombokRefactoring_no_types; + public static String LombokRefactoring_title; + public static String LombokRefactoringDescriptor_not_registered; + public static String RefactoringElement_does_not_match_type; + public static String RefactoringElement_impossible_binary; + public static String RefactoringElement_non_existing_type; + public static String RefactoringElement_not_consistent; + public static String RefactoringElement_type_name_compilation_unit; + public static String RefactoringElement_type_name_package; + public static String RefactoringElement_type_name_package_root; + public static String RefactoringElement_type_name_project; + public static String RefactoringElement_type_name_type; + public static String RefactoringElement_unknown_structure; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/src/lombok/eclipse/i18n/messages.properties b/src/lombok/eclipse/i18n/messages.properties new file mode 100644 index 0000000..b5ce006 --- /dev/null +++ b/src/lombok/eclipse/i18n/messages.properties @@ -0,0 +1,33 @@ +LombokRefactorAction_unsupported_element=Unsupported element selected: {0} +LombokRefactorAction_wizard_title=Refactor to Lombok Annotations +LombokRefactoringWizard_title=Refactor boilerplate Java to Lombok +LombokRefactoringWizardPage_equals_hashcode_check=Change equals and hashCode to @EqualsAndHashCode annotation +LombokRefactoringWizardPage_getter_check=Change getters to @Getter annotation +LombokRefactoringWizardPage_message=Select the refactorings to apply for the {0} selected elements. +LombokRefactoringWizardPage_setter_check=Change setters to @Setter annotation +LombokRefactoringWizardPage_tostring_check=Change toString to @ToString annotation +LombokRefactoring_change_comment_element={0} ''{1}'' +LombokRefactoring_change_comment_elements_title=Selected Elements: +LombokRefactoring_change_comment_equals_hashcode=Refactoring Equals and HashCode: {0} +LombokRefactoring_change_comment_getter=Refactoring Getter: {0} +LombokRefactoring_change_comment_project=Project: {0} +LombokRefactoring_change_comment_setter=Refactoring Setter: {0} +LombokRefactoring_change_comment_tostring=Refactoring toString: {0} +LombokRefactoring_change_description=Changing {1} elements in project ''{0}'' to use Lombok annotations +LombokRefactoring_create_change_monitor_begin=Creating change... +LombokRefactoring_final_condition_monitor_begin=Sanity check +LombokRefactoring_initial_condition_monitor_begin=Checking preconditions +LombokRefactoring_more_than_one_project=Only one project allowed +LombokRefactoring_no_types=No type(s) selected +LombokRefactoring_title=Use Lombok Annotations +LombokRefactoringDescriptor_not_registered=Refactoring contribution registered for id '{0}' returned null as result of createDescriptor(String, String, String, String, Map, int) +RefactoringElement_does_not_match_type=Element does not match expected type: {0} +RefactoringElement_impossible_binary=Refactoring of binary types is not possible: {0} +RefactoringElement_non_existing_type=Non existing type: {0} +RefactoringElement_not_consistent=Not consistent: {0} +RefactoringElement_type_name_compilation_unit=Compilation Unit +RefactoringElement_type_name_package=Package +RefactoringElement_type_name_package_root=Package Root +RefactoringElement_type_name_project=Project +RefactoringElement_type_name_type=Type +RefactoringElement_unknown_structure=Unknown structure: {0} diff --git a/src/lombok/eclipse/internal/LombokEclipsePlugin.java b/src/lombok/eclipse/internal/LombokEclipsePlugin.java new file mode 100644 index 0000000..197277a --- /dev/null +++ b/src/lombok/eclipse/internal/LombokEclipsePlugin.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2009 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.eclipse.internal; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + * + * @author gransberger + */ +public class LombokEclipsePlugin extends AbstractUIPlugin { + + // The plug-in ID + public static final String PLUGIN_ID = "lombok.eclipse"; //$NON-NLS-1$ + + // The shared instance + private static LombokEclipsePlugin plugin; + + /** + * The constructor + */ + public LombokEclipsePlugin() { + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext + * ) + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext + * ) + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static LombokEclipsePlugin getDefault() { + return plugin; + } + + public static class Logger { + + public static void error(Exception e) { + LombokEclipsePlugin.getDefault().getLog().log(new Status(IStatus.ERROR, LombokEclipsePlugin.PLUGIN_ID, e.getMessage(), e)); + } + + public static void error(String message, Exception e) { + LombokEclipsePlugin.getDefault().getLog().log(new Status(IStatus.ERROR, LombokEclipsePlugin.PLUGIN_ID, message, e)); + } + + public static void error(String message) { + LombokEclipsePlugin.getDefault().getLog().log(new Status(IStatus.ERROR, LombokEclipsePlugin.PLUGIN_ID, message)); + } + + public static void warn(String message) { + LombokEclipsePlugin.getDefault().getLog().log(new Status(IStatus.WARNING, LombokEclipsePlugin.PLUGIN_ID, message)); + } + + } + +} diff --git a/src/lombok/eclipse/internal/LombokIdentifiers.java b/src/lombok/eclipse/internal/LombokIdentifiers.java new file mode 100644 index 0000000..f50628a --- /dev/null +++ b/src/lombok/eclipse/internal/LombokIdentifiers.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2009 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.eclipse.internal; + +public final class LombokIdentifiers { + + //TODO change to use Lombok Project + public static final String ACCESS_LEVEL_PACKAGE = "PACKAGE"; //$NON-NLS-1$ + public static final String ACCESS_LEVEL_PROTECTED = "PROTECTED"; //$NON-NLS-1$ + public static final String ACCESS_LEVEL_PRIVATE = "PRIVATE"; //$NON-NLS-1$ + public static final String LOMBOK_ACCESS_LEVEL = "lombok.AccessLevel"; //$NON-NLS-1$ + public static final String LOMBOK_GETTER = "lombok.Getter"; //$NON-NLS-1$ + public static final String LOMBOK_SETTER = "lombok.Setter"; //$NON-NLS-1$ + public static final String LOMBOK_EQUALS_HASHCODE = "lombok.EqualsAndHashCode"; //$NON-NLS-1$ + public static final String LOMBOK_TOSTRING = "lombok.ToString"; //$NON-NLS-1$ + + private LombokIdentifiers() { + throw new AssertionError(); + } + +} diff --git a/src/lombok/eclipse/refactoring/ASTUtils.java b/src/lombok/eclipse/refactoring/ASTUtils.java new file mode 100644 index 0000000..02c9eed --- /dev/null +++ b/src/lombok/eclipse/refactoring/ASTUtils.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2009 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.eclipse.refactoring; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.ASTVisitor; +import org.eclipse.jdt.core.dom.Annotation; +import org.eclipse.jdt.core.dom.Block; +import org.eclipse.jdt.core.dom.BodyDeclaration; +import org.eclipse.jdt.core.dom.IBinding; +import org.eclipse.jdt.core.dom.MarkerAnnotation; +import org.eclipse.jdt.core.dom.MethodDeclaration; +import org.eclipse.jdt.core.dom.NormalAnnotation; +import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.dom.SingleMemberAnnotation; +import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.jdt.core.dom.rewrite.ListRewrite; + +public final class ASTUtils { + + private ASTUtils() { + throw new AssertionError(); + } + + public static boolean isAnnotationPresent(ASTNode node, String annotationName) { + AnnotationFinder finder = new AnnotationFinder(); + node.accept(finder); + + for (Annotation annotation : finder.getAnnotations()) { + String typeName = annotation.getTypeName().getFullyQualifiedName(); + if (typeName.equals(annotationName)) { + return true; + } + } + return false; + } + + public static boolean isAnnotationPresent(ASTRewrite astRewrite, BodyDeclaration node, String annotationName) { + ListRewrite listRewrite = astRewrite.getListRewrite(node, node.getModifiersProperty()); + for (Object o : listRewrite.getRewrittenList()) { + if (ASTUtils.isAnnotationPresent((ASTNode) o, annotationName)) { + return true; + } + } + return false; + } + + /** + * Resolves and returns the binding for the given node, if there's a + * binding. + * + * @param node + * @return The resolved binding of the node or null if none was + * found. + */ + public static IBinding getBinding(ASTNode node) { + BindingFinder finder = new BindingFinder(); + node.accept(finder); + return finder.getBinding(); + } + + /** + * Get the statements of the body of the given method. + * + * @param node + * The method + * @return A List of statements from the body of the method. + * @see org.eclipse.jdt.core.dom.Block#statements() + */ + public static List getStatements(MethodDeclaration node) { + Block body = node.getBody(); + if (body == null) { + // abstract method/interface + return Collections.emptyList(); + } + @SuppressWarnings("unchecked") + List statements = body.statements(); + return statements; + } + + /** + * Determines if the given node was auto-generated instead of beeing created + * from hand-written code. + * + * @param node + * @return true if the code was generated (f.e. by Lombok) + */ + public static boolean isGenerated(ASTNode node) { + return GeneratedBy.isGenerated(node); + } + + // ##### + + private static class GeneratedBy { + private static Field generatedByField; + + static { + try { + generatedByField = ASTNode.class.getDeclaredField("$isGenerated"); //$NON-NLS-1$ + } catch (Throwable t) { + // ignore - no $generatedBy exists when running in ecj. + } + } + + public static Boolean getGeneratedBy(ASTNode node) { + if (generatedByField != null) { + try { + return (Boolean) generatedByField.get(node); + } catch (Exception e) { + } + } + return Boolean.FALSE; + } + + public static boolean isGenerated(ASTNode node) { + return Boolean.TRUE.equals(getGeneratedBy(node)); + } + } + + private static class AnnotationFinder extends ASTVisitor { + + private final List annotations = new ArrayList(); + + @Override + public boolean visit(MarkerAnnotation node) { + this.annotations.add(node); + return super.visit(node); + } + + @Override + public boolean visit(NormalAnnotation node) { + this.annotations.add(node); + return super.visit(node); + } + + @Override + public boolean visit(SingleMemberAnnotation node) { + this.annotations.add(node); + return super.visit(node); + } + + public List getAnnotations() { + return this.annotations; + } + + } + + private static class BindingFinder extends ASTVisitor { + + private IBinding binding; + + public IBinding getBinding() { + return this.binding; + } + + @Override + public boolean visit(SimpleName node) { + this.binding = node.resolveBinding(); + return super.visit(node); + } + + } +} diff --git a/src/lombok/eclipse/refactoring/LombokRefactoring.java b/src/lombok/eclipse/refactoring/LombokRefactoring.java new file mode 100644 index 0000000..2fb5d45 --- /dev/null +++ b/src/lombok/eclipse/refactoring/LombokRefactoring.java @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2009 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.eclipse.refactoring; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import lombok.eclipse.i18n.Messages; +import lombok.eclipse.internal.LombokEclipsePlugin.Logger; +import lombok.eclipse.refactoring.LombokRefactoringDescriptor.Attributes; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.core.dom.AST; +import org.eclipse.jdt.core.dom.ASTParser; +import org.eclipse.jdt.core.dom.ASTRequestor; +import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.ChangeDescriptor; +import org.eclipse.ltk.core.refactoring.CompositeChange; +import org.eclipse.ltk.core.refactoring.Refactoring; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.ltk.core.refactoring.TextFileChange; +import org.eclipse.text.edits.MalformedTreeException; +import org.eclipse.text.edits.MultiTextEdit; +import org.eclipse.text.edits.TextEdit; + +public class LombokRefactoring extends Refactoring { + + private final Map unitChanges = new LinkedHashMap(); + private final LombokRefactoringDescriptor descriptor; + private final List elements; + + public LombokRefactoring(LombokRefactoringDescriptor descriptor) { + this.descriptor = descriptor; + this.elements = new ArrayList(descriptor.getArguments().getElements()); + } + + @Override + public String getName() { + return Messages.LombokRefactoring_title; + } + + public int getNumberOfElements() { + return this.elements.size(); + } + + public LombokRefactoringDescriptor getDescriptor() { + return this.descriptor; + } + + @Override + public RefactoringStatus checkInitialConditions(IProgressMonitor monitor) throws CoreException, + OperationCanceledException { + try { + monitor.beginTask(Messages.LombokRefactoring_initial_condition_monitor_begin, 1); + + RefactoringStatus status = new RefactoringStatus(); + if (this.elements == null || this.elements.isEmpty()) { + status.addError(Messages.LombokRefactoring_no_types); + } else { + for (RefactoringElement element : this.elements) { + element.updateStatus(status); + } + } + return status; + } finally { + monitor.done(); + } + } + + @Override + public RefactoringStatus checkFinalConditions(IProgressMonitor monitor) throws CoreException, + OperationCanceledException { + try { + monitor.beginTask(Messages.LombokRefactoring_final_condition_monitor_begin, 1); + + final RefactoringStatus status = new RefactoringStatus(); + + this.unitChanges.clear(); + + Set units = new HashSet(); + IJavaProject selectedProject = queryCompilationUnits(status, units); + + processCompilationUnits(status, selectedProject, units); + + return status; + } finally { + monitor.done(); + } + } + + @Override + public Change createChange(IProgressMonitor monitor) throws CoreException, OperationCanceledException { + try { + monitor.beginTask(Messages.LombokRefactoring_create_change_monitor_begin, 1); + final Collection changes = this.unitChanges.values(); + final CompositeChange change = new LombokCompositeChange(getName(), changes); + return change; + } finally { + monitor.done(); + } + } + + private IJavaProject queryCompilationUnits(final RefactoringStatus status, Set units) + throws JavaModelException { + IJavaProject selectedProject = null; + try { + for (RefactoringElement element : this.elements) { + if (selectedProject == null) { + selectedProject = element.getJavaProject(); + } + if (!element.getJavaProject().equals(selectedProject)) { + throw new IllegalStateException(Messages.LombokRefactoring_more_than_one_project); + } + + units.addAll(element.getCompilationUnits()); + } + } catch (IllegalStateException e) { + status.addError(e.getMessage()); + } + return selectedProject; + } + + private void processCompilationUnits(final RefactoringStatus status, IJavaProject project, + Set units) { + ASTRequestor requestors = new ASTRequestor() { + + @Override + public void acceptAST(ICompilationUnit source, CompilationUnit ast) { + try { + rewriteCompilationUnit(this, source, ast, status); + } catch (CoreException exception) { + exception.printStackTrace(); + } + } + }; + ASTParser parser = ASTParser.newParser(AST.JLS3); + parser.setProject(project); + parser.setResolveBindings(true); + parser.createASTs(units.toArray(new ICompilationUnit[units.size()]), new String[0], requestors, + new NullProgressMonitor()); + } + + protected void rewriteCompilationUnit(ASTRequestor requestor, ICompilationUnit unit, CompilationUnit node, + RefactoringStatus status) throws CoreException { + ASTRewrite astRewrite = ASTRewrite.create(node.getAST()); + ImportRewrite importRewrite = ImportRewrite.create(node, true); + + refactor(requestor, astRewrite, importRewrite, unit, node); + + rewriteAST(unit, astRewrite, importRewrite); + } + + private void refactor(ASTRequestor requestor, ASTRewrite astRewrite, ImportRewrite importRewrite, + ICompilationUnit unit, CompilationUnit node) { + LombokRefactoringVisitor visitor = new LombokRefactoringVisitor(this); + node.accept(visitor); + visitor.refactor(astRewrite, importRewrite); + } + + private void rewriteAST(ICompilationUnit unit, ASTRewrite astRewrite, ImportRewrite importRewrite) { + try { + MultiTextEdit edit = new MultiTextEdit(); + TextEdit astEdit = astRewrite.rewriteAST(); + + if (!isEmptyEdit(astEdit)) { + edit.addChild(astEdit); + } + TextEdit importEdit = importRewrite.rewriteImports(new NullProgressMonitor()); + if (!isEmptyEdit(importEdit)) { + edit.addChild(importEdit); + } + if (isEmptyEdit(edit)) { + return; + } + + addChange(unit, edit); + } catch (MalformedTreeException e) { + Logger.error(e); + } catch (CoreException e) { + Logger.error(e); + } + } + + private void addChange(ICompilationUnit unit, MultiTextEdit edit) { + TextFileChange change = this.unitChanges.get(unit); + if (change == null) { + change = new TextFileChange(unit.getElementName(), (IFile) unit.getResource()); + change.setTextType("java"); //$NON-NLS-1$ + change.setEdit(edit); + + this.unitChanges.put(unit, change); + } else { + change.getEdit().addChild(edit); + } + } + + private boolean isEmptyEdit(TextEdit edit) { + return edit.getClass() == MultiTextEdit.class && !edit.hasChildren(); + } + + public boolean canApply() { + Attributes arguments = this.descriptor.getArguments(); + return arguments.isRefactorEqualsHashCode() || arguments.isRefactorGetters() || arguments.isRefactorSetters() + || arguments.isRefactorToString(); + } + + private final class LombokCompositeChange extends CompositeChange { + + private LombokCompositeChange(String name, Collection changes) { + super(name, changes.toArray(new Change[changes.size()])); + } + + @Override + public ChangeDescriptor getDescriptor() { + return LombokRefactoring.this.descriptor.getChange(); + } + } + +} diff --git a/src/lombok/eclipse/refactoring/LombokRefactoringContribution.java b/src/lombok/eclipse/refactoring/LombokRefactoringContribution.java new file mode 100644 index 0000000..4058d07 --- /dev/null +++ b/src/lombok/eclipse/refactoring/LombokRefactoringContribution.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2009 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.eclipse.refactoring; + +import java.util.Map; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.ltk.core.refactoring.Refactoring; +import org.eclipse.ltk.core.refactoring.RefactoringContribution; +import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; + +/** + * + * @author gransberger + * + */ +public class LombokRefactoringContribution extends RefactoringContribution { + + @Override + public RefactoringDescriptor createDescriptor() { + return new LombokRefactoringDescriptor(); + } + + @SuppressWarnings("unchecked") + @Override + public RefactoringDescriptor createDescriptor(String id, String project, String description, String comment, + @SuppressWarnings("rawtypes") Map arguments, int flags) throws IllegalArgumentException { + LombokRefactoringDescriptor descr = new LombokRefactoringDescriptor(project, description, comment); + descr.getArguments().putAll(arguments); + return descr; + } + + @SuppressWarnings("rawtypes") + @Override + public Map retrieveArgumentMap(RefactoringDescriptor descriptor) { + return ((LombokRefactoringDescriptor) descriptor).getArguments(); + } + + public Refactoring createRefactoring(LombokRefactoringDescriptor descriptor, RefactoringStatus status) + throws CoreException { + return new LombokRefactoring(descriptor); + } + +} diff --git a/src/lombok/eclipse/refactoring/LombokRefactoringDescriptor.java b/src/lombok/eclipse/refactoring/LombokRefactoringDescriptor.java new file mode 100644 index 0000000..ff08e1d --- /dev/null +++ b/src/lombok/eclipse/refactoring/LombokRefactoringDescriptor.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2009 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.eclipse.refactoring; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +import lombok.eclipse.i18n.Messages; +import lombok.eclipse.internal.LombokEclipsePlugin.Logger; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.ltk.core.refactoring.ChangeDescriptor; +import org.eclipse.ltk.core.refactoring.Refactoring; +import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor; +import org.eclipse.ltk.core.refactoring.RefactoringContribution; +import org.eclipse.ltk.core.refactoring.RefactoringCore; +import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; + +public class LombokRefactoringDescriptor extends RefactoringDescriptor { + private static final String LINE_DELIMITER = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ + private static final String ITEM = "- "; //$NON-NLS-1$ + + public static final String ID = "lombok.eclipse.refactoring.tolombok"; //$NON-NLS-1$ + + private static final String UNKNOWN = "unknown"; //$NON-NLS-1$ + + private final Attributes arguments = new Attributes(); + + public LombokRefactoringDescriptor() { + super(ID, null, UNKNOWN, null, RefactoringDescriptor.NONE); + } + + public LombokRefactoringDescriptor(String project, String description, String comment) { + super(ID, project, description, comment, RefactoringDescriptor.NONE); + } + + public Attributes getArguments() { + return this.arguments; + } + + /** + * {@inheritDoc} + */ + @Override + public Refactoring createRefactoring(final RefactoringStatus status) throws CoreException { + LombokRefactoring refactoring = null; + final String id = getID(); + final RefactoringContribution contribution = RefactoringCore.getRefactoringContribution(id); + if (contribution != null) { + if (contribution instanceof LombokRefactoringContribution) { + LombokRefactoringContribution lombokContrib = (LombokRefactoringContribution) contribution; + refactoring = (LombokRefactoring) lombokContrib.createRefactoring(this, status); + } else { + String message = MessageFormat.format(Messages.LombokRefactoringDescriptor_not_registered, id); + Logger.error(message); + } + } + return refactoring; + } + + public ChangeDescriptor getChange() { + Attributes oldArguments = getArguments(); + Collection elements = oldArguments.getElements(); + + IJavaProject javaProject = elements.iterator().next().getJavaProject(); + String project = javaProject.getElementName(); + String description = MessageFormat.format(Messages.LombokRefactoring_change_description, new Object[] { + project, elements.size() }); + + StringBuilder comments = new StringBuilder(); + comments.append(ITEM) + .append(MessageFormat.format(Messages.LombokRefactoring_change_comment_project, + javaProject.getElementName())).append(LINE_DELIMITER); + comments.append(ITEM) + .append(MessageFormat.format(Messages.LombokRefactoring_change_comment_getter, + String.valueOf(oldArguments.isRefactorGetters()))).append(LINE_DELIMITER); + comments.append(ITEM) + .append(MessageFormat.format(Messages.LombokRefactoring_change_comment_setter, + String.valueOf(oldArguments.isRefactorSetters()))).append(LINE_DELIMITER); + comments.append(ITEM) + .append(MessageFormat.format(Messages.LombokRefactoring_change_comment_equals_hashcode, + String.valueOf(oldArguments.isRefactorEqualsHashCode()))).append(LINE_DELIMITER); + comments.append(ITEM) + .append(MessageFormat.format(Messages.LombokRefactoring_change_comment_tostring, + String.valueOf(oldArguments.isRefactorToString()))).append(LINE_DELIMITER); + comments.append(ITEM).append(Messages.LombokRefactoring_change_comment_elements_title); + for (RefactoringElement element : elements) { + comments.append( + MessageFormat.format(Messages.LombokRefactoring_change_comment_element, element.getTypeName(), + element.getElementName())).append(", "); //$NON-NLS-1$ + } + comments.append(LINE_DELIMITER); + + LombokRefactoringDescriptor descr = new LombokRefactoringDescriptor(project, description, comments.toString()); + Attributes arguments = descr.getArguments(); + arguments.putAll(oldArguments); + arguments.setProject(javaProject); + arguments.setElements(elements); + + return new RefactoringChangeDescriptor(descr); + } + + public static class Attributes extends HashMap { + + private static final long serialVersionUID = 4870727884514586453L; + + public static final String ATTRIBUTE_PROJECT = "project"; //$NON-NLS-1$ + public static final String ATTRIBUTE_REFACTOR_GETTERS = "getters"; //$NON-NLS-1$ + public static final String ATTRIBUTE_REFACTOR_SETTERS = "setters"; //$NON-NLS-1$ + public static final String ATTRIBUTE_REFACTOR_EQUALS_HASHCODE = "equalsHashCode"; //$NON-NLS-1$ + public static final String ATTRIBUTE_REFACTOR_TOSTRING = "toString"; //$NON-NLS-1$ + public static final String ATTRIBUTE_ELEMENTS = "elements"; //$NON-NLS-1$ + + public void setProject(IJavaProject project) { + put(ATTRIBUTE_PROJECT, project.getElementName()); + } + + public void setRefactorGetters(boolean refactorGetters) { + put(ATTRIBUTE_REFACTOR_GETTERS, String.valueOf(refactorGetters)); + } + + public void setRefactorSetters(boolean refactorSetters) { + put(ATTRIBUTE_REFACTOR_SETTERS, String.valueOf(refactorSetters)); + } + + public void setRefactorEqualsAndHashCode(boolean refactor) { + put(ATTRIBUTE_REFACTOR_EQUALS_HASHCODE, String.valueOf(refactor)); + } + + public void setRefactorToString(boolean refactor) { + put(ATTRIBUTE_REFACTOR_TOSTRING, String.valueOf(refactor)); + } + + public void setElements(Collection elements) { + StringBuilder elementsBuilder = new StringBuilder(); + for (RefactoringElement e : elements) { + elementsBuilder.append(e.getHandleIdentifier()).append(";"); //$NON-NLS-1$ + } + + put(ATTRIBUTE_ELEMENTS, elementsBuilder.toString()); + } + + public boolean isRefactorToString() { + return Boolean.parseBoolean(get(ATTRIBUTE_REFACTOR_TOSTRING)); + } + + public boolean isRefactorGetters() { + return Boolean.parseBoolean(get(ATTRIBUTE_REFACTOR_GETTERS)); + } + + public boolean isRefactorSetters() { + return Boolean.parseBoolean(get(ATTRIBUTE_REFACTOR_SETTERS)); + } + + public boolean isRefactorEqualsHashCode() { + return Boolean.parseBoolean(get(ATTRIBUTE_REFACTOR_EQUALS_HASHCODE)); + } + + protected Collection getElements() { + List elements = new ArrayList(); + String string = get(ATTRIBUTE_ELEMENTS); + + String[] split = string.split(";"); + if (split != null) { + for (String s : split) { + if (s.trim().length() > 0) { + elements.add(RefactoringElement.Factory.create(JavaCore.create(s))); + } + } + } + return elements; + } + + } +} \ No newline at end of file diff --git a/src/lombok/eclipse/refactoring/LombokRefactoringVisitor.java b/src/lombok/eclipse/refactoring/LombokRefactoringVisitor.java new file mode 100644 index 0000000..bbf81dd --- /dev/null +++ b/src/lombok/eclipse/refactoring/LombokRefactoringVisitor.java @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2009 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.eclipse.refactoring; + +import static lombok.eclipse.refactoring.ASTUtils.*; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import lombok.eclipse.internal.LombokIdentifiers; +import lombok.eclipse.refactoring.LombokRefactoringDescriptor.Attributes; + +import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.ASTVisitor; +import org.eclipse.jdt.core.dom.Annotation; +import org.eclipse.jdt.core.dom.Assignment; +import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.ExpressionStatement; +import org.eclipse.jdt.core.dom.FieldAccess; +import org.eclipse.jdt.core.dom.FieldDeclaration; +import org.eclipse.jdt.core.dom.IBinding; +import org.eclipse.jdt.core.dom.MarkerAnnotation; +import org.eclipse.jdt.core.dom.MethodDeclaration; +import org.eclipse.jdt.core.dom.Modifier; +import org.eclipse.jdt.core.dom.ReturnStatement; +import org.eclipse.jdt.core.dom.SimpleName; +import org.eclipse.jdt.core.dom.SingleMemberAnnotation; +import org.eclipse.jdt.core.dom.SingleVariableDeclaration; +import org.eclipse.jdt.core.dom.TypeDeclaration; +import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; +import org.eclipse.jdt.core.dom.rewrite.ListRewrite; + +public class LombokRefactoringVisitor extends ASTVisitor { + + private final List fields = new ArrayList(); + private final List getters = new ArrayList(); + private final List setters = new ArrayList(); + private final List equalsHashCode = new ArrayList(); + private final List toString = new ArrayList(); + + private final LombokRefactoring refactoring; + + public LombokRefactoringVisitor(LombokRefactoring refactoring) { + this.refactoring = refactoring; + } + + @Override + public boolean visit(FieldDeclaration node) { + this.fields.add(node); + return true; + } + + @Override + public boolean visit(MethodDeclaration node) { + if (isGenerated(node)) { + return true; + } + String identifier = node.getName().getIdentifier(); + LombokRefactoringDescriptor descriptor = this.refactoring.getDescriptor(); + Attributes arguments = descriptor.getArguments(); + if (arguments.isRefactorGetters() && (identifier.startsWith("get") || identifier.startsWith("is"))) { //$NON-NLS-1$ //$NON-NLS-2$ + analzyeGetter(node); + } else if (arguments.isRefactorSetters() && identifier.startsWith("set")) { //$NON-NLS-1$ + analyzeSetter(node); + } else if (arguments.isRefactorEqualsHashCode() && (identifier.startsWith("equals"))) { //$NON-NLS-1$ + analyzeEquals(node);// TODO canEqual + } else if (arguments.isRefactorEqualsHashCode() && (identifier.startsWith("hashCode"))) { //$NON-NLS-1$ + analyzeHashCode(node); + } else if (arguments.isRefactorToString() && identifier.startsWith("toString")) { //$NON-NLS-1$ + analyzeToString(node); + } + + return true; + } + + public void refactor(ASTRewrite astRewrite, ImportRewrite importRewrite) { + LombokRewriter rewriter = new LombokRewriter(astRewrite, importRewrite, this); + rewriter.refactorGetters(); + rewriter.refactorSetters(); + rewriter.refactorEqualsHashCode(); + rewriter.refactorToString(); + } + + private void analzyeGetter(MethodDeclaration node) { + List statements = getStatements(node); + if (statements.size() == 1) { + for (Iterator it = statements.iterator(); it.hasNext();) { + ASTNode child = it.next(); + if (child.getNodeType() == ASTNode.RETURN_STATEMENT) { + this.getters.add(node); + } + } + } + } + + private void analyzeSetter(MethodDeclaration node) { + List statements = getStatements(node); + if (statements.size() == 1) { + for (Iterator it = statements.iterator(); it.hasNext();) { + ASTNode child = it.next(); + if (child.getNodeType() == ASTNode.EXPRESSION_STATEMENT + && ((ExpressionStatement) child).getExpression().getNodeType() == ASTNode.ASSIGNMENT) { + this.setters.add(node); + } + } + } + } + + private void analyzeToString(MethodDeclaration node) { + if (Modifier.isPublic(node.getModifiers())) { + if (node.getReturnType2().resolveBinding().getQualifiedName().equals(String.class.getName())) { + List parameters = node.parameters(); + if (parameters.isEmpty()) { + this.toString.add(node); + } + } + } + } + + private void analyzeEquals(MethodDeclaration node) { + if (Modifier.isPublic(node.getModifiers())) { + if (node.getReturnType2().resolveBinding().getQualifiedName().equals(boolean.class.getName())) { + @SuppressWarnings("unchecked") + List parameters = node.parameters(); + if (parameters.size() == 1) { + SingleVariableDeclaration parameterNode = parameters.get(0); + if (parameterNode.getType().resolveBinding().getQualifiedName().equals(Object.class.getName())) { + this.equalsHashCode.add(node); + } + } + } + } + } + + private void analyzeHashCode(MethodDeclaration node) { + if (Modifier.isPublic(node.getModifiers())) { + if (node.getReturnType2().resolveBinding().getQualifiedName().equals(int.class.getName())) { + List parameters = node.parameters(); + if (parameters.isEmpty()) { + this.equalsHashCode.add(node); + } + } + } + } + + private static class LombokRewriter { + + private final ImportRewrite importRewrite; + private final ASTRewrite astRewrite; + private final LombokRefactoringVisitor visitor; + + public LombokRewriter(ASTRewrite astRewrite, ImportRewrite importRewrite, LombokRefactoringVisitor visitor) { + this.astRewrite = astRewrite; + this.importRewrite = importRewrite; + this.visitor = visitor; + } + + private void refactorSetters() { + for (MethodDeclaration method : this.visitor.setters) { + refactorSetter(method); + } + } + + private void refactorGetters() { + for (MethodDeclaration method : this.visitor.getters) { + refactorGetter(method); + } + } + + private void refactorEqualsHashCode() { + for (MethodDeclaration method : this.visitor.equalsHashCode) { + refactorEqualsHashCode(method); + } + } + + private void refactorToString() { + for (MethodDeclaration method : this.visitor.toString) { + refactorToString(method); + } + } + + private void refactorSetter(MethodDeclaration method) { + // this.value = value; + Assignment statement = (Assignment) ((ExpressionStatement) method.getBody().statements().get(0)) + .getExpression(); + Expression lhs = statement.getLeftHandSide(); + if (lhs.getNodeType() == ASTNode.FIELD_ACCESS) { + FieldDeclaration field = checkMatch(((FieldAccess) lhs).getName()); + if (field != null) { + Expression rightHandSide = statement.getRightHandSide(); + if (rightHandSide.getNodeType() == ASTNode.SIMPLE_NAME) { + String setterType = this.importRewrite.addImport(LombokIdentifiers.LOMBOK_SETTER); + addAnnotationToField(field, setterType, method.getModifiers()); + this.astRewrite.remove(method, null); + } + } + } + } + + private void refactorGetter(MethodDeclaration method) { + // return this.value; + ReturnStatement statement = (ReturnStatement) method.getBody().statements().get(0); + Expression expression = statement.getExpression(); + FieldDeclaration field = checkMatch(expression); + if (field != null) { + String getterType = this.importRewrite.addImport(LombokIdentifiers.LOMBOK_GETTER); + + addAnnotationToField(field, getterType, method.getModifiers()); + + this.astRewrite.remove(method, null); + } + } + + private void refactorEqualsHashCode(MethodDeclaration method) { + String annotationType = this.importRewrite.addImport(LombokIdentifiers.LOMBOK_EQUALS_HASHCODE); + addAnnotationToType(method, annotationType); + + this.astRewrite.remove(method, null); + } + + private void refactorToString(MethodDeclaration method) { + String annotationType = this.importRewrite.addImport(LombokIdentifiers.LOMBOK_TOSTRING); + + addAnnotationToType(method, annotationType); + + this.astRewrite.remove(method, null); + } + + public void addAnnotationToType(MethodDeclaration method, String annotationType) { + TypeDeclaration typeNode = (TypeDeclaration) method.getParent(); + + if (!ASTUtils.isAnnotationPresent(this.astRewrite, typeNode, annotationType)) { + MarkerAnnotation annotation = typeNode.getAST().newMarkerAnnotation(); + annotation.setTypeName(typeNode.getAST().newName(annotationType)); + + ListRewrite listRewrite = this.astRewrite.getListRewrite(typeNode, typeNode.getModifiersProperty()); + listRewrite.insertFirst(annotation, null); + } + + } + + private void addAnnotationToField(FieldDeclaration field, String annotationName, int modifiers) { + if (!ASTUtils.isAnnotationPresent(this.astRewrite, field, annotationName)) { + // import lombok.AccessLevel; + // PUBLIC, PROTECTED, PACKAGE, and PRIVATE. + final Annotation annotation; + if (Modifier.isPublic(modifiers)) { + // default + MarkerAnnotation newMarkerAnnotation = field.getAST().newMarkerAnnotation(); + annotation = newMarkerAnnotation; + } else { + String accessLevelType = this.importRewrite.addImport(LombokIdentifiers.LOMBOK_ACCESS_LEVEL); + + SingleMemberAnnotation singleAnnotation = field.getAST().newSingleMemberAnnotation(); + + FieldAccess newFieldAccess = field.getAST().newFieldAccess(); + newFieldAccess.setExpression(field.getAST().newSimpleName(accessLevelType)); + newFieldAccess.setName(field.getAST().newSimpleName(getFieldNameForModifier(modifiers))); + singleAnnotation.setValue(newFieldAccess); + + annotation = singleAnnotation; + } + annotation.setTypeName(field.getAST().newName(annotationName)); + + this.astRewrite.getListRewrite(field, field.getModifiersProperty()).insertFirst(annotation, null); + } + } + + private String getFieldNameForModifier(int modifiers) { + final String fieldName; + if (Modifier.isPrivate(modifiers)) { + fieldName = LombokIdentifiers.ACCESS_LEVEL_PRIVATE; + } else if (Modifier.isProtected(modifiers)) { + fieldName = LombokIdentifiers.ACCESS_LEVEL_PROTECTED; + } else { + fieldName = LombokIdentifiers.ACCESS_LEVEL_PACKAGE; + } + return fieldName; + } + + private FieldDeclaration checkMatch(Expression expression) { + if (expression.getNodeType() == ASTNode.SIMPLE_NAME) { + SimpleName simple = (SimpleName) expression; + IBinding expressionBinding = simple.resolveBinding(); + if (expressionBinding != null) { + for (FieldDeclaration field : this.visitor.fields) { + IBinding binding = getBinding(field); + if (expressionBinding.equals(binding)) { + return field; + } + } + } + } + return null; + } + } + +} diff --git a/src/lombok/eclipse/refactoring/RefactoringElement.java b/src/lombok/eclipse/refactoring/RefactoringElement.java new file mode 100644 index 0000000..3c50531 --- /dev/null +++ b/src/lombok/eclipse/refactoring/RefactoringElement.java @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2009 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.eclipse.refactoring; + +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import lombok.eclipse.i18n.Messages; + +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.IType; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; + +public interface RefactoringElement { + + public int getElementType(); + + public Collection getCompilationUnits() throws JavaModelException; + + public String getHandleIdentifier(); + + public String getElementName(); + + public String getTypeName(); + + public IJavaProject getJavaProject(); + + public void updateStatus(RefactoringStatus status) throws JavaModelException; + + public static class Factory { + public static RefactoringElement create(IJavaElement element) { + if (element.getElementType() == IJavaElement.TYPE) { + return new TypeRefactoringElement(element); + } + if (element.getElementType() == IJavaElement.COMPILATION_UNIT) { + return new CompilationUnitRefactoringElement(element); + } + if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT) { + return new PackageRefactoringElement(element); + } + if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT) { + return new PackageRootRefactoringElement(element); + } + if (element.getElementType() == IJavaElement.TYPE || element.getElementType() == IJavaElement.JAVA_PROJECT) { + return new ProjectRefactoringElement(element); + } + return null; + } + } + + public static abstract class ARefactoringElement implements RefactoringElement { + protected final IJavaElement element; + + public ARefactoringElement(IJavaElement element) { + if (element.getElementType() != getElementType()) { + throw new IllegalArgumentException(MessageFormat.format( + Messages.RefactoringElement_does_not_match_type, getElementType())); + } + this.element = element; + } + + @Override + public void updateStatus(RefactoringStatus status) throws JavaModelException { + if (!element.exists()) { + status.addError(MessageFormat.format(Messages.RefactoringElement_non_existing_type, + element.getElementName())); + } + if (!element.isStructureKnown()) { + status.addError(MessageFormat.format(Messages.RefactoringElement_unknown_structure, + element.getElementName())); + } + } + + @Override + public String getHandleIdentifier() { + return element.getHandleIdentifier(); + } + + @Override + public String getElementName() { + return element.getElementName(); + } + + @Override + public IJavaProject getJavaProject() { + return element.getJavaProject(); + } + + } + + public static class TypeRefactoringElement extends ARefactoringElement { + + public TypeRefactoringElement(IJavaElement element) { + super(element); + } + + @Override + public int getElementType() { + return IJavaElement.TYPE; + } + + @Override + public String getTypeName() { + return Messages.RefactoringElement_type_name_type; + } + + @Override + public Collection getCompilationUnits() { + IType type = (IType) element; + ICompilationUnit unit = type.getCompilationUnit(); + return Collections.singleton(unit); + } + + @Override + public void updateStatus(RefactoringStatus status) throws JavaModelException { + if (((IType) element).isBinary()) { + status.addError(MessageFormat.format(Messages.RefactoringElement_impossible_binary, + element.getElementName())); + } + super.updateStatus(status); + } + + } + + public static class CompilationUnitRefactoringElement extends ARefactoringElement { + + public CompilationUnitRefactoringElement(IJavaElement element) { + super(element); + } + + @Override + public int getElementType() { + return IJavaElement.COMPILATION_UNIT; + } + + @Override + public String getTypeName() { + return Messages.RefactoringElement_type_name_compilation_unit; + } + + @Override + public Collection getCompilationUnits() { + ICompilationUnit unit = (ICompilationUnit) element; + return Collections.singleton(unit); + } + + @Override + public void updateStatus(RefactoringStatus status) throws JavaModelException { + if (!((ICompilationUnit) element).isConsistent()) { + status.addError(MessageFormat.format(Messages.RefactoringElement_not_consistent, + element.getElementName())); + } + super.updateStatus(status); + } + + } + + public static class PackageRefactoringElement extends ARefactoringElement { + + public PackageRefactoringElement(IJavaElement element) { + super(element); + } + + @Override + public int getElementType() { + return IJavaElement.PACKAGE_FRAGMENT; + } + + @Override + public String getTypeName() { + return Messages.RefactoringElement_type_name_package; + } + + @Override + public Collection getCompilationUnits() throws JavaModelException { + IPackageFragment packag = (IPackageFragment) element; + return Arrays.asList(packag.getCompilationUnits()); + } + + } + + public static class PackageRootRefactoringElement extends ARefactoringElement { + + public PackageRootRefactoringElement(IJavaElement element) { + super(element); + } + + @Override + public int getElementType() { + return IJavaElement.PACKAGE_FRAGMENT_ROOT; + } + + @Override + public String getTypeName() { + return Messages.RefactoringElement_type_name_package_root; + } + + @Override + public Collection getCompilationUnits() throws JavaModelException { + IPackageFragmentRoot srcFolder = (IPackageFragmentRoot) element; + Set units = new HashSet(); + for (IJavaElement child : srcFolder.getChildren()) { + Collection childUnits = Factory.create(child).getCompilationUnits(); + units.addAll(childUnits); + } + return units; + } + + } + + public static class ProjectRefactoringElement extends ARefactoringElement { + + public ProjectRefactoringElement(IJavaElement element) { + super(element); + } + + @Override + public int getElementType() { + return IJavaElement.JAVA_PROJECT; + } + + @Override + public String getTypeName() { + return Messages.RefactoringElement_type_name_project; + } + + @Override + public Collection getCompilationUnits() throws JavaModelException { + IJavaProject project = (IJavaProject) element; + Set units = new HashSet(); + + for (IPackageFragment fragment : project.getPackageFragments()) { + Collection childUnits = Factory.create(fragment).getCompilationUnits(); + units.addAll(childUnits); + } + return units; + } + + } + +} diff --git a/src/lombok/eclipse/wizards/LombokRefactoringWizard.java b/src/lombok/eclipse/wizards/LombokRefactoringWizard.java new file mode 100644 index 0000000..731f814 --- /dev/null +++ b/src/lombok/eclipse/wizards/LombokRefactoringWizard.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2009 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.eclipse.wizards; + +import lombok.eclipse.i18n.Messages; +import lombok.eclipse.refactoring.LombokRefactoring; + +import org.eclipse.ltk.ui.refactoring.RefactoringWizard; + +public class LombokRefactoringWizard extends RefactoringWizard { + + private final LombokRefactoring refactoring; + + public LombokRefactoringWizard(LombokRefactoring refactoring) { + super(refactoring, WIZARD_BASED_USER_INTERFACE | PREVIEW_EXPAND_FIRST_NODE); + this.refactoring = refactoring; + setDefaultPageTitle(Messages.LombokRefactoringWizard_title); + } + + @Override + protected void addUserInputPages() { + addPage(new LombokRefactoringWizardPage("LombokRefactorWizardPage", this.refactoring)); //$NON-NLS-1$ + } +} \ No newline at end of file diff --git a/src/lombok/eclipse/wizards/LombokRefactoringWizardPage.java b/src/lombok/eclipse/wizards/LombokRefactoringWizardPage.java new file mode 100644 index 0000000..c25fcd9 --- /dev/null +++ b/src/lombok/eclipse/wizards/LombokRefactoringWizardPage.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2009 The Project Lombok Authors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package lombok.eclipse.wizards; + +import java.text.MessageFormat; + +import lombok.eclipse.i18n.Messages; +import lombok.eclipse.refactoring.LombokRefactoring; +import lombok.eclipse.refactoring.LombokRefactoringDescriptor; +import lombok.eclipse.refactoring.LombokRefactoringDescriptor.Attributes; + +import org.eclipse.ltk.ui.refactoring.UserInputWizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; + +public class LombokRefactoringWizardPage extends UserInputWizardPage { + + private final LombokRefactoring refactoring; + private Button setterButton; + private Button getterButton; + private Button equalsHashCodeButton; + private Button toStringButton; + + public LombokRefactoringWizardPage(String name, LombokRefactoring refactoring) { + super(name); + this.refactoring = refactoring; + } + + @Override + public void createControl(Composite parent) { + Composite result = new Composite(parent, SWT.NONE); + + setControl(result); + + GridLayout layout = new GridLayout(); + layout.numColumns = 1; + result.setLayout(layout); + + setMessage(MessageFormat.format(Messages.LombokRefactoringWizardPage_message, + this.refactoring.getNumberOfElements())); + + this.getterButton = new Button(result, SWT.CHECK); + this.getterButton.setText(Messages.LombokRefactoringWizardPage_getter_check); + + this.setterButton = new Button(result, SWT.CHECK); + this.setterButton.setText(Messages.LombokRefactoringWizardPage_setter_check); + + // FIXME + this.equalsHashCodeButton = new Button(result, SWT.CHECK); + this.equalsHashCodeButton.setText(Messages.LombokRefactoringWizardPage_equals_hashcode_check); + + this.toStringButton = new Button(result, SWT.CHECK); + this.toStringButton.setText(Messages.LombokRefactoringWizardPage_tostring_check); + + // ###### + final SelectionListener inputChangeListener = new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + handleInputChanged(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + widgetSelected(e); + } + }; + this.getterButton.addSelectionListener(inputChangeListener); + this.setterButton.addSelectionListener(inputChangeListener); + this.equalsHashCodeButton.addSelectionListener(inputChangeListener); + this.toStringButton.addSelectionListener(inputChangeListener); + + // ###### + + this.getterButton.setSelection(true); + this.setterButton.setSelection(true); + this.equalsHashCodeButton.setSelection(true); + this.toStringButton.setSelection(true); + + // ###### + + handleInputChanged(); + } + + void handleInputChanged() { + LombokRefactoringDescriptor descriptor = this.refactoring.getDescriptor(); + Attributes arguments = descriptor.getArguments(); + + arguments.setRefactorGetters(this.getterButton.getSelection()); + arguments.setRefactorSetters(this.setterButton.getSelection()); + arguments.setRefactorEqualsAndHashCode(this.equalsHashCodeButton.getSelection()); + arguments.setRefactorToString(this.toStringButton.getSelection()); + setPageComplete(this.refactoring.canApply()); + } + +} \ No newline at end of file