diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index d450e392b5..ca718990b1 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -31,12 +31,62 @@ All of the following variants to specify a version are now possible: ``` +## new `quickfix` and `cleanup` mojo + +Keeping code up-todate is a daunting task and Eclipse IDE can be a great help due to its offering for automatic quick-fixes and cleanup actions. +Still this has usually be applied manually (or automatic on save) and requires some user interaction. + +There is now a new `tycho-cleancode:cleanup` and `tycho-cleancode:quickfix` mojo that help with these things to be called via automation or part of the build, +both mojos run by default in the process-sources phase so any later compilation can verify the outcome easily. Due to the way they work internally, +they require an eclipse project to be present and configured currently. + +The `tycho-cleancode:cleanup` mojo allows to configure the desired cleanup profile in the pom (maybe inside a profile), the values are those that you will find +when exporting a profile from the IDE. If no profile is given the default from the project are used: + +```xml + + org.eclipse.tycho + tycho-cleancode-plugin + ${tycho-version} + + + cleanup + + cleanup + + + + true + + + + + +``` + +The `tycho-cleancode:quickfix` mojo simply apply the quick fix with the highest relevance for resolution and can be enabled like this (maybe inside a profile): + +```xml + + org.eclipse.tycho + tycho-cleancode-plugin + ${tycho-version} + + + quickfix + + quickfix + + + + +``` ## new `check-dependencies` mojo When using version ranges there is a certain risk that one actually uses some methods from never release and it goes unnoticed. -There is now a new `tycho-baseline:dependencies mojo` that analyze the compiled class files for used method references and compares them to +There is now a new `tycho-baseline:dependencies` mojo that analyze the compiled class files for used method references and compares them to the individual artifacts that match the version range. To find these versions it uses the maven metadata stored in P2 as well as the eclipse-repository index to find possible candidates. @@ -47,7 +97,7 @@ according to the discovered problems, a configuration for this might look like t org.eclipse.tycho tycho-baseline-plugin - ${tycho.version} + ${tycho-version} checkit diff --git a/pom.xml b/pom.xml index f31487437f..e5101ee219 100644 --- a/pom.xml +++ b/pom.xml @@ -596,6 +596,7 @@ tycho-repository-plugin tycho-eclipse-plugin tycho-wrap-plugin + tycho-cleancode-plugin diff --git a/tycho-cleancode-plugin/.settings/org.eclipse.jdt.core.prefs b/tycho-cleancode-plugin/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..eeac0e762f --- /dev/null +++ b/tycho-cleancode-plugin/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/tycho-cleancode-plugin/pom.xml b/tycho-cleancode-plugin/pom.xml new file mode 100644 index 0000000000..74848cd3c8 --- /dev/null +++ b/tycho-cleancode-plugin/pom.xml @@ -0,0 +1,64 @@ + + 4.0.0 + + org.eclipse.tycho + tycho + 5.0.0-SNAPSHOT + + tycho-cleancode-plugin + Tycho Eclipse Plugin + maven-plugin + + ${minimal-maven-version} + + Maven Plugins for performing automatic code clean options + + + org.apache.maven + maven-core + + + org.apache.maven + maven-plugin-api + + + org.apache.maven.plugin-tools + maven-plugin-annotations + + + org.eclipse.tycho + tycho-eclipse-plugin + ${project.version} + + + org.eclipse.jdt + org.eclipse.jdt.ui + 3.33.200 + + + org.eclipse.jdt + org.eclipse.jdt.core.manipulation + 1.21.300 + + + + + + + org.codehaus.plexus + plexus-component-metadata + + + org.apache.maven.plugins + maven-plugin-plugin + + + tycho-cleancode + + + + + \ No newline at end of file diff --git a/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/CleanUp.java b/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/CleanUp.java new file mode 100644 index 0000000000..6c85f26204 --- /dev/null +++ b/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/CleanUp.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) 2025 Christoph Läubrich and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.tycho.cleancode; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.ProjectScope; +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.JavaCore; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.internal.corext.fix.CleanUpPreferenceUtil; +import org.eclipse.jdt.internal.corext.fix.CleanUpRefactoring; +import org.eclipse.jdt.internal.ui.JavaPlugin; +import org.eclipse.jdt.internal.ui.fix.MapCleanUpOptions; +import org.eclipse.jdt.ui.cleanup.CleanUpOptions; +import org.eclipse.jdt.ui.cleanup.ICleanUp; +import org.eclipse.ltk.core.refactoring.Change; +import org.eclipse.ltk.core.refactoring.PerformChangeOperation; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.tycho.eclipsebuild.AbstractEclipseBuild; + +public class CleanUp extends AbstractEclipseBuild { + + private Map customProfile; + + CleanUp(Path projectDir, boolean debug, Map customProfile) { + super(projectDir, debug); + this.customProfile = customProfile; + } + + @Override + protected CleanupResult createResult(IProject project) throws Exception { + CleanupResult result = new CleanupResult(); + CleanUpOptions options = getOptions(project); + ICleanUp[] cleanups = getCleanups(result, options); + if (cleanups.length > 0) { + List units = getCompilationUnits(project); + final CleanUpRefactoring refactoring = new CleanUpRefactoring(project.getName()); + for (ICompilationUnit cu : units) { + refactoring.addCompilationUnit(cu); + } + refactoring.setUseOptionsFromProfile(false); + for (ICleanUp cleanUp : cleanups) { + refactoring.addCleanUp(cleanUp); + } + final RefactoringStatus status = refactoring.checkAllConditions(this); + if (status.isOK()) { + Change change = refactoring.createChange(this); + change.initializeValidationData(this); + PerformChangeOperation performChangeOperation = new PerformChangeOperation(change); + performChangeOperation.run(this); + } else if (status.hasError()) { + throw new RuntimeException("Refactoring failed: " + status); + } + } + return result; + } + + private List getCompilationUnits(IProject project) throws JavaModelException { + IJavaProject javaProject = JavaCore.create(project); + List units = new ArrayList(); + IPackageFragmentRoot[] packages = javaProject.getPackageFragmentRoots(); + for (IPackageFragmentRoot root : packages) { + if (root.getKind() == IPackageFragmentRoot.K_SOURCE) { + for (IJavaElement javaElement : root.getChildren()) { + if (javaElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT) { + IPackageFragment pf = (IPackageFragment) javaElement; + ICompilationUnit[] compilationUnits = pf.getCompilationUnits(); + for (ICompilationUnit compilationUnit : compilationUnits) { + units.add(compilationUnit); + } + } + } + } + } + return units; + } + + private ICleanUp[] getCleanups(CleanupResult result, CleanUpOptions options) { + ICleanUp[] cleanUps = JavaPlugin.getDefault().getCleanUpRegistry().createCleanUps(); + for (ICleanUp cleanUp : cleanUps) { + try { + cleanUp.setOptions(options); + String[] descriptions = cleanUp.getStepDescriptions(); + if (descriptions != null) { + for (String description : descriptions) { + result.addCleanup(description); + } + } + } catch (Exception e) { + debug("Ignore cleanup '" + cleanUp + "' because of initialization error.", e); + } + } + return cleanUps; + } + + private CleanUpOptions getOptions(IProject project) { + Map options; + if (customProfile == null || customProfile.isEmpty()) { + options = CleanUpPreferenceUtil.loadOptions(new ProjectScope(project)); + } else { + options = customProfile; + } + debug("Cleanup Profile: " + options.entrySet().stream().map(e -> e.getKey() + " = " + e.getValue()) + .collect(Collectors.joining(System.lineSeparator()))); + return new MapCleanUpOptions(options); + } + +} diff --git a/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/CleanUpMojo.java b/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/CleanUpMojo.java new file mode 100644 index 0000000000..c76a103bed --- /dev/null +++ b/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/CleanUpMojo.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.tycho.cleancode; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.eclipse.tycho.eclipsebuild.AbstractEclipseBuildMojo; +import org.eclipse.tycho.model.project.EclipseProject; + +/** + * This mojo allows to perform eclipse cleanup action + */ +@Mojo(name = "cleanup", defaultPhase = LifecyclePhase.PROCESS_SOURCES, threadSafe = true, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME) +public class CleanUpMojo extends AbstractEclipseBuildMojo { + + @Parameter(defaultValue = "${project.build.directory}/cleanups.md", property = "tycho.cleanup.report") + private File reportFileName; + + /** + * Defines key value pairs of a cleanup profile, if not defined will use the + * project defaults + */ + @Parameter + private Map cleanUpProfile; + + @Override + protected String[] getRequireBundles() { + return new String[] { "org.eclipse.jdt.ui" }; + } + + @Override + protected String getName() { + return "Perform Cleanup"; + } + + @Override + protected CleanUp createExecutable() { + return new CleanUp(project.getBasedir().toPath(), debug, cleanUpProfile); + } + + @Override + protected void handleResult(CleanupResult result) + throws MojoFailureException { + List results = new ArrayList<>(); + results.add("The following cleanups where applied:"); + result.cleanups().forEach(cleanup -> { + results.add("- " + cleanup); + }); + try { + Files.writeString(reportFileName.toPath(), + results.stream().collect(Collectors.joining(System.lineSeparator()))); + } catch (IOException e) { + throw new MojoFailureException(e); + } + } + + @Override + protected boolean isValid(EclipseProject eclipseProject) { + // Cleanups can only be applied to java projects + return eclipseProject.hasNature("org.eclipse.jdt.core.javanature"); + } + +} diff --git a/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/CleanupResult.java b/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/CleanupResult.java new file mode 100644 index 0000000000..11b2d45623 --- /dev/null +++ b/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/CleanupResult.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2025 Christoph Läubrich and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.tycho.cleancode; + +import java.util.Set; +import java.util.TreeSet; +import java.util.stream.Stream; + +import org.eclipse.tycho.eclipsebuild.EclipseBuildResult; + +public class CleanupResult extends EclipseBuildResult { + + private Set cleanups = new TreeSet(); + + public void addCleanup(String cleanup) { + cleanups.add(cleanup); + } + + public Stream cleanups() { + return this.cleanups.stream(); + } + +} diff --git a/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/QuickFix.java b/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/QuickFix.java new file mode 100644 index 0000000000..a76f23c22a --- /dev/null +++ b/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/QuickFix.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2025 Christoph Läubrich and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.tycho.cleancode; + +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Comparator; +import java.util.concurrent.atomic.AtomicReference; + +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.tycho.eclipsebuild.AbstractEclipseBuild; +import org.eclipse.ui.IMarkerResolution; +import org.eclipse.ui.IMarkerResolution2; +import org.eclipse.ui.IMarkerResolutionRelevance; +import org.eclipse.ui.ide.IDE; + +/** + * Applies the QuickFix with the highest relevance to a warning, because + * QuickFixes are not really optimized to run in a CI build we need to be very + * forgiving here and handle errors gracefully. + */ +public class QuickFix extends AbstractEclipseBuild { + + QuickFix(Path projectDir, boolean debug) { + super(projectDir, debug); + } + + @Override + protected QuickFixResult createResult(IProject project) throws Exception { + QuickFixResult result = new QuickFixResult(); + IMarker[] markers = project.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); + result.setNumberOfMarker(markers.length); + for (IMarker marker : markers) { + debug("Marker: " + marker); + try { + IMarkerResolution[] resolutions = IDE.getMarkerHelpRegistry().getResolutions(marker); + debug("Marker has " + resolutions.length + " resolutions"); + IMarkerResolution resolution = Arrays.stream(resolutions) + .max(Comparator.comparingInt(r -> getRelevance(r))).orElse(null); + if (resolution != null) { + debug("Apply best resolution to marker: " + getInfo(resolution)); + // must use an own thread to make sure it is not called as a job + AtomicReference error = new AtomicReference(); + Thread thread = new Thread(new Runnable() { + + @Override + public void run() { + try { + resolution.run(marker); + } catch (Throwable t) { + error.set(t); + } + } + }); + thread.start(); + thread.join(); + Throwable t = error.get(); + if (t == null) { + result.addFix(buildFixMessage(marker)); + } else { + debug("Marker could not be applied!", t); + } + } + } catch (Throwable t) { + debug("Marker resolutions could not be computed!", t); + } + } + return result; + } + + private String buildFixMessage(IMarker marker) { + StringBuilder sb = new StringBuilder(marker.getAttribute(IMarker.MESSAGE, "Unknown Problem")); + IResource resource = marker.getResource(); + if (resource != null) { + sb.append(" in "); + sb.append(resource.getFullPath()); + int line = marker.getAttribute(IMarker.LINE_NUMBER, -1); + if (line > 0) { + sb.append(" at line "); + sb.append(line); + } + } + return sb.toString(); + } + + private String getInfo(IMarkerResolution resolution) { + if (resolution instanceof IMarkerResolution2 res2) { + return resolution.getClass().getName() + ": " + getLabel(resolution) + " // " + getDescription(res2); + } else { + return resolution.getClass().getName() + ": " + getLabel(resolution); + } + } + + private int getRelevance(IMarkerResolution resolution) { + try { + if (resolution instanceof IMarkerResolutionRelevance relevance) { + return relevance.getRelevanceForResolution(); + } + } catch (RuntimeException e) { + } + return -1; + } + + private String getDescription(IMarkerResolution2 markerResolution) { + try { + return markerResolution.getDescription(); + } catch (RuntimeException e) { + return null; + } + } + + private String getLabel(IMarkerResolution resolution) { + try { + return resolution.getLabel(); + } catch (RuntimeException e) { + return resolution.getClass().getName(); + } + } + +} diff --git a/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/QuickFixMojo.java b/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/QuickFixMojo.java new file mode 100644 index 0000000000..5b4f5b96fc --- /dev/null +++ b/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/QuickFixMojo.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2025 Christoph Läubrich and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.tycho.cleancode; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.eclipse.tycho.eclipsebuild.AbstractEclipseBuildMojo; + +@Mojo(name = "quickfix", defaultPhase = LifecyclePhase.PROCESS_SOURCES, threadSafe = true, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME) +public class QuickFixMojo extends AbstractEclipseBuildMojo { + + @Parameter(defaultValue = "${project.build.directory}/quickfix.md", property = "tycho.quickfix.report") + private File reportFileName; + + @Override + protected void handleResult(QuickFixResult result) throws MojoFailureException { + List results = new ArrayList<>(); + if (result.getMarkers() == 0) { + results.add("Project is clean!"); + } else { + List fixes = result.fixes().toList(); + if (fixes.isEmpty()) { + results.add("Nothing has been resolved in this project."); + } else { + results.add("The following " + (fixes.size() > 0 ? "warnings" : "warning") + " has been resolved:"); + fixes.forEach(fix -> { + results.add("- " + fix); + }); + } + } + try { + Files.writeString(reportFileName.toPath(), + results.stream().collect(Collectors.joining(System.lineSeparator()))); + } catch (IOException e) { + throw new MojoFailureException(e); + } + } + + @Override + protected String[] getRequireBundles() { + return new String[] { "org.eclipse.ui.ide", "org.eclipse.jdt.ui" }; + } + + @Override + protected QuickFix createExecutable() { + return new QuickFix(project.getBasedir().toPath(), debug); + } + + @Override + protected String getName() { + return "Quick Fix"; + } + +} diff --git a/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/QuickFixResult.java b/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/QuickFixResult.java new file mode 100644 index 0000000000..8bacea8902 --- /dev/null +++ b/tycho-cleancode-plugin/src/main/java/org/eclipse/tycho/cleancode/QuickFixResult.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2025 Christoph Läubrich and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.tycho.cleancode; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import org.eclipse.tycho.eclipsebuild.EclipseBuildResult; + +public class QuickFixResult extends EclipseBuildResult { + + private List fixed = new ArrayList<>(); + private int markers; + + public Stream fixes() { + return fixed.stream(); + } + + public void addFix(String fix) { + fixed.add(fix); + } + + public void setNumberOfMarker(int markers) { + this.markers = markers; + } + + public int getMarkers() { + return markers; + } + +} diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuild.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuild.java index 199607b938..46c449db14 100644 --- a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuild.java +++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuild.java @@ -1,7 +1,9 @@ package org.eclipse.tycho.eclipsebuild; import java.io.IOException; +import java.io.PrintWriter; import java.io.Serializable; +import java.io.StringWriter; import java.nio.file.Path; import java.util.concurrent.Callable; @@ -83,6 +85,14 @@ protected void debug(String string) { } } + protected void debug(String string, Throwable t) { + if (debug) { + StringWriter writer = new StringWriter(); + t.printStackTrace(new PrintWriter(writer)); + debug(string + System.lineSeparator() + writer); + } + } + static String pathAsString(Path path) { if (path != null) { return path.toAbsolutePath().toString(); diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuildMojo.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuildMojo.java index c9e4717f3a..6fc02b9209 100644 --- a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuildMojo.java +++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuildMojo.java @@ -96,6 +96,9 @@ public final void execute() throws MojoExecutionException, MojoFailureException return; } EclipseProject eclipseProject = eclipseProjectValue.get(); + if (!isValid(eclipseProject)) { + return; + } Collection projectDependencies; try { projectDependencies = projectManager.getProjectDependencies(project); @@ -145,6 +148,10 @@ public final void execute() throws MojoExecutionException, MojoFailureException } } + protected boolean isValid(EclipseProject eclipseProject) { + return true; + } + protected abstract void handleResult(Result result) throws MojoFailureException; protected abstract AbstractEclipseBuild createExecutable();