diff --git a/_ext/greclipse/LICENSE.txt b/_ext/eclipse-groovy/LICENSE.txt
similarity index 100%
rename from _ext/greclipse/LICENSE.txt
rename to _ext/eclipse-groovy/LICENSE.txt
diff --git a/_ext/eclipse-groovy/README.md b/_ext/eclipse-groovy/README.md
new file mode 100644
index 0000000000..8850ecd75c
--- /dev/null
+++ b/_ext/eclipse-groovy/README.md
@@ -0,0 +1,14 @@
+# spotless-eclipse-groovy
+
+Groovy-Eclipse is not available in a form which can be easily consumed by maven or gradle.
+To fix this, we publish Groovy-Eclipse's formatter and all its dependencies, along with a small amount of glue code, into the `com.diffplug.gradle.spotless:spotless-eclipse-groovy` artifact.
+
+## Build
+
+To publish a new version, update the `_ext/eclipse-groovy/gradle.properties` appropriately and run this from the root directory:
+
+```
+gradlew -b _ext/eclipse-groovy/build.gradle publish
+```
+
+Spotless at large is under the Apache 2.0 license, but this jar is under the EPL v1.
diff --git a/_ext/eclipse-groovy/build.gradle b/_ext/eclipse-groovy/build.gradle
new file mode 100644
index 0000000000..bb2c6a9a22
--- /dev/null
+++ b/_ext/eclipse-groovy/build.gradle
@@ -0,0 +1,179 @@
+import java.io.File
+
+import org.apache.commons.io.filefilter.DirectoryFileFilter
+
+plugins {
+ // p2 dependencies
+ id 'com.diffplug.gradle.p2.asmaven' version '3.9.0'
+}
+
+apply from: rootProject.file('../gradle/java-setup.gradle')
+apply from: rootProject.file('../gradle/java-publish.gradle')
+
+// The dependencies to pull from GrEclipse's p2 repositories
+def grEclipseDeps = [
+ 'org.codehaus.groovy.eclipse.refactoring':'+', // GroovyFormatter and related
+
+ // The following lists does not reflect the complete transitive required packages, but
+ // the once used during code formatting
+ 'org.codehaus.groovy':'+', // Groovy compiler patches supporting use within GrEclipse and Groovy itself
+ 'org.codehaus.groovy.eclipse.core':'+', // Groovy core classes (provides central logging used by formatter)
+ 'org.eclipse.jdt.core':"${VER_JDT_PATCH}", // Patches org.eclipse.jdt.core classes supporting use within GrEclipse (provides AST generator)
+ 'org.eclipse.jdt.groovy.core':'+' // Extends org.eclipse.jdt.core for Groovy
+]
+
+ext {
+ developers = [
+ fvgh: [ name: 'Frank Vennemeyer', email: 'frankgh@zoho.com' ],
+ ]
+
+ //Include/Excludes form the JARs, which goes into a fat-jar with the spottless formatter interface.
+ jarInclude = [
+ '**/*.class', // Take all classes
+ '**/*.java', // ... and sources.
+ '**/*.properties', // Text resources (for messages, etc)
+ '**/*.xml', // Plugin XML and other resources
+ '*.html', // License information about the included JARs,
+ 'META-INF/**' // Information about the origin of the individual class files
+ ]
+ jarExclude = [
+ 'META-INF/*.RSA', // The eclipse jars are signed, and our fat-jar breaks the signatures
+ 'META-INF/*.SF', // ... so all signatures are filtered
+ ]
+
+ //Some JARs include JARs themselfs
+ internalJars = [
+ //Jars included by org.codehaus.groovy
+ "**/groovy-all-${VER_GROOVY}-indy", // Use Groovy compiler compatible with GrEclipse instead of localGroovy
+ '**/groovy-eclipse', // Patches/Overrides some of the Groovy compiler classes
+ '**/eclipse-trace', // Provides logging capabilities for groovy-eclipse
+
+ //Jars included by org.eclipse.jdt.groovy.core
+ '**/nlcl' //Non locking class loader used by groovy compiler
+ ]
+
+ // The directory contains all external classes for the fat-jar
+ embeddedClassesDirName = 'build/embeddedClasses'
+ embeddedClassesDir = project.file(embeddedClassesDirName)
+ embeddedClassesLibDirName = 'build/embeddedClasses/lib'
+ embeddedClassesLibDir = project.file(embeddedClassesLibDirName)
+}
+
+// build a maven repo in our build folder containing these artifacts
+p2AsMaven {
+ group 'p2', {
+ repo "http://dist.springsource.org/release/GRECLIPSE/e${VER_ECLIPSE}"
+ grEclipseDeps.keySet.each { p2.addIU(it) }
+ }
+}
+
+configurations {
+ embeddedJars // GrEclipse JARs the fat-jar is based uppon
+}
+
+dependencies {
+ grEclipseDeps.each { groupArtifact, version ->
+ embeddedJars "p2:${groupArtifact}:${version}"
+ }
+
+ // The resulting fat-jar includes the classes from GRECLIPSE.
+ compile files(embeddedClassesDir)
+
+ compile "com.diffplug.spotless:spotless-eclipse-base:${VER_SPOTLESS_ECLISPE_BASE}"
+ // Provides text partitioners for formatters
+ compile ("org.eclipse.platform:org.eclipse.jface.text:${VER_ECLISPE_JFACE}") {
+ exclude group: 'org.eclipse.platform', module: 'org.eclipse.swt'
+ }
+}
+
+jar {
+ // this embeds the Eclipse-Groovy clases into our "fat JAR"
+ from embeddedClassesDir
+}
+
+//////////
+// Test //
+//////////
+sourceSets {
+ // Use JAR file with all resources for Eclipse-Groovy integration-tests
+ test.runtimeClasspath = jar.outputs.files + sourceSets.test.output + sourceSets.test.compileClasspath
+}
+
+///////////////////
+// External Deps //
+///////////////////
+
+task unjarEmbeddedClasses {
+ description = "Copies filtered set of embedded classes from the Eclise/GrEclipse dependencies to '${project.relativePath(embeddedClassesDir)}'."
+ inputs.files(configurations.embeddedJars)
+ inputs.property('internalJars', internalJars)
+ inputs.property('jarInclude', jarInclude)
+ inputs.property('jarExclude', jarExclude)
+ outputs.file(embeddedClassesDir)
+
+ doLast {
+ embeddedClassesDir.deleteDir()
+ embeddedClassesDir.mkdirs()
+ embeddedClassesLibDir.deleteDir()
+ embeddedClassesLibDir.mkdirs()
+ configurations.embeddedJars.each {
+ unjar(it, embeddedClassesDir)
+ }
+ //Unpack internal JARs. Maintain the order defined in internalJars
+ internalJars.each {
+ fileTree(embeddedClassesDir).include("${it}.jar").each {
+ unjar(it, embeddedClassesDir)
+ delete(it)
+ }
+ }
+ }
+}
+
+def unjar(File jarFile, File destDir) {
+ ant.unjar(src: jarFile, dest: destDir) {
+ patternset {
+ jarInclude.each {
+ include(name: "${it}")
+ }
+ internalJars.each {
+ include(name: "**/${it}.jar")
+ }
+ jarExclude.each {
+ exclude(name: "${it}")
+ }
+ }
+ }
+ //Provide Fat JAR resources (following naming convention of spotless-eclipse-base)
+ def fat_jar_resource_dir = jarFile.getName().split('-')[0]
+ ant.move(todir: "${destDir}/${fat_jar_resource_dir}/META-INF", quiet: 'true', failonerror: 'false') {
+ fileset(dir: "${destDir}/META-INF")
+ }
+ //Keep licenses and other human readable information for transparency
+ ant.move(todir: "${destDir}/${fat_jar_resource_dir}", quiet: 'true') {
+ fileset(dir: destDir) {
+ include(name: 'META-INF')
+ include(name: '*')
+ type(type: 'file')
+ exclude(name: '*jar-*')
+ exclude(name: '*.jar')
+ }
+ }
+}
+
+tasks.compileJava.dependsOn(unjarEmbeddedClasses)
+
+/////////
+// IDE //
+/////////
+
+apply plugin: 'eclipse'
+
+// always create fresh projects
+tasks.eclipse.dependsOn(cleanEclipse)
+// Encure that the dependent classes are preovided for compilation if project is build via Eclipse instead of command line
+tasks.eclipseClasspath.dependsOn(unjarEmbeddedClasses)
+
+apply plugin: 'idea'
+
+// Encure that the dependent classes are preovided for compilation if project is build via Eclipse instead of command line
+tasks.idea.dependsOn(unjarEmbeddedClasses)
diff --git a/_ext/eclipse-groovy/gradle.properties b/_ext/eclipse-groovy/gradle.properties
new file mode 100644
index 0000000000..766a0c9639
--- /dev/null
+++ b/_ext/eclipse-groovy/gradle.properties
@@ -0,0 +1,19 @@
+# Versions correspond to the Eclipse-Groovy version used for th FAT JAR
+# See https://github.com/groovy/groovy-eclipse/releases for further information about Eclipse-Groovy versions.
+# Patch version can be is incremented independently for backward compatible patches of this library.
+ext_version=2.9.2
+ext_artifactId=spotless-eclipse-groovy
+ext_description=Groovy Eclipse's formatter bundled for Spotless
+
+ext_org=diffplug
+ext_group=com.diffplug.spotless
+
+# Build requirements
+ext_VER_JAVA=1.8
+
+# Compile
+VER_ECLIPSE=4.7
+VER_SPOTLESS_ECLISPE_BASE=[3.0.0,4.0.0[
+VER_ECLISPE_JFACE=[3.12.0,4.0.0[
+VER_GROOVY=2.5.0
+VER_JDT_PATCH=3.13.100.xx-201801041714-e47-RELEASE
diff --git a/_ext/greclipse/src/main/java/com/diffplug/gradle/spotless/groovy/eclipse/GrEclipseFormatterStepImpl.java b/_ext/eclipse-groovy/src/main/java/com/diffplug/spotless/extra/eclipse/groovy/GrEclipseFormatterStepImpl.java
similarity index 62%
rename from _ext/greclipse/src/main/java/com/diffplug/gradle/spotless/groovy/eclipse/GrEclipseFormatterStepImpl.java
rename to _ext/eclipse-groovy/src/main/java/com/diffplug/spotless/extra/eclipse/groovy/GrEclipseFormatterStepImpl.java
index 815f5f1226..2c507a34d9 100644
--- a/_ext/greclipse/src/main/java/com/diffplug/gradle/spotless/groovy/eclipse/GrEclipseFormatterStepImpl.java
+++ b/_ext/eclipse-groovy/src/main/java/com/diffplug/spotless/extra/eclipse/groovy/GrEclipseFormatterStepImpl.java
@@ -13,15 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.diffplug.gradle.spotless.groovy.eclipse;
+package com.diffplug.spotless.extra.eclipse.groovy;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.util.LinkedList;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Properties;
+import org.codehaus.groovy.eclipse.GroovyLogManager;
+import org.codehaus.groovy.eclipse.IGroovyLogger;
+import org.codehaus.groovy.eclipse.TraceCategory;
import org.codehaus.groovy.eclipse.core.GroovyCoreActivator;
import org.codehaus.groovy.eclipse.refactoring.formatter.DefaultGroovyFormatter;
import org.codehaus.groovy.eclipse.refactoring.formatter.FormatterPreferencesOnStore;
@@ -29,54 +33,86 @@
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.ILogListener;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.equinox.log.ExtendedLogReaderService;
+import org.eclipse.equinox.log.ExtendedLogService;
import org.eclipse.jface.preference.PreferenceStore;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.text.edits.TextEdit;
+import com.diffplug.spotless.extra.eclipse.base.SpotlessEclipseFramework;
+
/** Spotless-Formatter step which calls out to the Groovy-Eclipse formatter. */
public class GrEclipseFormatterStepImpl {
+ /**
+ * Groovy compiler problems can be ignored.
+ *
+ * Value is either 'true' or 'false'
+ *
+ */
+ public static final String IGNORE_FORMATTER_PROBLEMS = "ignoreFormatterProblems";
+
private final FormatterPreferencesOnStore preferencesStore;
+ private final boolean ignoreFormatterProblems;
public GrEclipseFormatterStepImpl(final Properties properties) throws Exception {
+ SpotlessLogService logService = new SpotlessLogService();
+ if (SpotlessEclipseFramework.setup(
+ config -> {
+ config.applyDefault();
+ config.add(ExtendedLogService.class, logService);
+ config.add(ExtendedLogReaderService.class, logService);
+ },
+ plugins -> {
+ plugins.add(new GroovyCoreActivator());
+ })) {}
PreferenceStore preferences = createPreferences(properties);
preferencesStore = new FormatterPreferencesOnStore(preferences);
+ ignoreFormatterProblems = Boolean.parseBoolean(properties.getProperty(IGNORE_FORMATTER_PROBLEMS, "false"));
}
+ /** Formatting Groovy string */
public String format(String raw) throws Exception {
IDocument doc = new Document(raw);
GroovyErrorListener errorListener = new GroovyErrorListener();
TextSelection selectAll = new TextSelection(doc, 0, doc.getLength());
GroovyFormatter codeFormatter = new DefaultGroovyFormatter(selectAll, doc, preferencesStore, false);
TextEdit edit = codeFormatter.format();
- if (errorListener.errorsDetected()) {
+ if (!ignoreFormatterProblems && errorListener.errorsDetected()) {
throw new IllegalArgumentException(errorListener.toString());
}
edit.apply(doc);
return doc.get();
}
- private static class GroovyErrorListener implements ILogListener {
+ /**
+ * Eclipse Groovy formatter does not signal problems by its return value, but by logging errors.
+ */
+ private static class GroovyErrorListener implements ILogListener, IGroovyLogger {
private final List errors;
public GroovyErrorListener() {
- errors = new LinkedList();
+ /*
+ * We need a synchronized list here, in case multiple instantiations
+ * run in parallel.
+ */
+ errors = Collections.synchronizedList(new ArrayList());
ILog groovyLogger = GroovyCoreActivator.getDefault().getLog();
groovyLogger.addLogListener(this);
+ GroovyLogManager.manager.addLogger(this);
}
@Override
public void logging(final IStatus status, final String plugin) {
- if (!status.isOK()) {
- errors.add(status.getMessage());
- }
+ errors.add(status.getMessage());
}
public boolean errorsDetected() {
ILog groovyLogger = GroovyCoreActivator.getDefault().getLog();
groovyLogger.removeLogListener(this);
+ GroovyLogManager.manager.removeLogger(this);
return 0 != errors.size();
}
@@ -96,6 +132,22 @@ public String toString() {
return string.toString();
}
+ @Override
+ public boolean isCategoryEnabled(TraceCategory cat) {
+ /*
+ * Note that the compiler errors are just additionally caught here.
+ * They are also printed directly to System.err.
+ * See org.codehaus.jdt.groovy.internal.compiler.ast.GroovyCompilationUnitDeclaration.recordProblems
+ * for details.
+ */
+ return TraceCategory.COMPILER.equals(cat);
+ }
+
+ @Override
+ public void log(TraceCategory arg0, String arg1) {
+ errors.add(arg1);
+ }
+
}
private static PreferenceStore createPreferences(final Properties properties) throws IOException {
diff --git a/_ext/eclipse-groovy/src/main/java/com/diffplug/spotless/extra/eclipse/groovy/SpotlessLogService.java b/_ext/eclipse-groovy/src/main/java/com/diffplug/spotless/extra/eclipse/groovy/SpotlessLogService.java
new file mode 100644
index 0000000000..1dc27b09b2
--- /dev/null
+++ b/_ext/eclipse-groovy/src/main/java/com/diffplug/spotless/extra/eclipse/groovy/SpotlessLogService.java
@@ -0,0 +1,467 @@
+/*
+ * Copyright 2016 DiffPlug
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.diffplug.spotless.extra.eclipse.groovy;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Optional;
+import java.util.Set;
+
+import org.eclipse.core.internal.runtime.InternalPlatform;
+import org.eclipse.equinox.log.ExtendedLogReaderService;
+import org.eclipse.equinox.log.ExtendedLogService;
+import org.eclipse.equinox.log.LogFilter;
+import org.eclipse.equinox.log.Logger;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogEntry;
+import org.osgi.service.log.LogLevel;
+import org.osgi.service.log.LogListener;
+import org.osgi.service.log.LogService;
+import org.osgi.service.log.LoggerConsumer;
+
+/**
+ * Simple log service for errors and warnings.
+ * Unsupported methods are marked as deprecated and throw an {@link UnsupportedOperationException}
+ */
+public class SpotlessLogService implements ExtendedLogService, ExtendedLogReaderService {
+
+ public final static Set FATAL_SEVERITIES = Collections.unmodifiableSet(new HashSet(Arrays.asList(LogLevel.ERROR, LogLevel.WARN)));
+ private final Set listener = new HashSet();
+
+ @Override
+ @Deprecated
+ //Backward compatibility with Eclipse OSGI 3.12
+ public void log(int level, String message) {}
+
+ @Override
+ @Deprecated
+ //Backward compatibility with Eclipse OSGI 3.12
+ public void log(int level, String message, Throwable exception) {
+ log(level, message);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ @Deprecated
+ //Backward compatibility with Eclipse OSGI 3.12
+ public void log(ServiceReference sr, int level, String message) {
+ log(level, message);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ @Deprecated
+ //Backward compatibility with Eclipse OSGI 3.12
+ public void log(ServiceReference sr, int level, String message, Throwable exception) {
+ log(level, message, exception);
+ }
+
+ @Override
+ public void log(Object context, int level, String message) {
+ log(level, message);
+ }
+
+ @SuppressWarnings("deprecation") ////Backward compatibility with Eclipse OSGI 3.12
+ @Override
+ public void log(Object context, int level, String message, Throwable exception) {
+ LogLevel logLevel;
+ switch (level) {
+ case LogService.LOG_DEBUG:
+ logLevel = LogLevel.DEBUG;
+ break;
+ case LogService.LOG_INFO:
+ logLevel = LogLevel.INFO;
+ break;
+ case LogService.LOG_ERROR:
+ logLevel = LogLevel.ERROR;
+ break;
+ case LogService.LOG_WARNING:
+ logLevel = LogLevel.WARN;
+ break;
+ default:
+ logLevel = LogLevel.AUDIT;
+ }
+ log(new SimpleLogEntry(logLevel, message, exception));
+ }
+
+ @Override
+ public boolean isLoggable(int level) {
+ return true;
+ }
+
+ @Override
+ public String getName() {
+ return SpotlessLogService.class.getSimpleName();
+ }
+
+ @Override
+ public Logger getLogger(String loggerName) {
+ return this;
+ }
+
+ @Override
+ public Logger getLogger(Bundle bundle, String loggerName) {
+ return this;
+ }
+
+ @Override
+ public void addLogListener(LogListener listener) {
+ synchronized (this.listener) {
+ this.listener.add(listener);
+ }
+ }
+
+ @Override
+ public void removeLogListener(LogListener listener) {
+ synchronized (this.listener) {
+ this.listener.remove(listener);
+ }
+ }
+
+ public void log(LogEntry entry) {
+ if (FATAL_SEVERITIES.contains(entry.getLogLevel())) {
+ synchronized (listener) {
+ if (0 != listener.size()) {
+ System.err.println(entry.toString());
+ listener.stream().forEach(l -> l.logged(entry));
+ }
+ }
+ }
+ }
+
+ @Override
+ @Deprecated
+ //Backward compatibility with Eclipse OSGI 3.12
+ public Enumeration getLog() {
+ return Collections.emptyEnumeration(); //We do not provide historical information
+ }
+
+ @Override
+ public void addLogListener(LogListener listener, LogFilter filter) {
+ addLogListener(listener); //Listener must filter if required
+
+ }
+
+ @Override
+ public org.osgi.service.log.Logger getLogger(Class> clazz) {
+ return this;
+ }
+
+ @Override
+ @Deprecated
+ public L getLogger(String name, Class loggerType) {
+ throw new UnsupportedOperationException("Logger Factory currently not supported.");
+ }
+
+ @Override
+ @Deprecated
+ public L getLogger(Class> clazz, Class loggerType) {
+ return getLogger(getName(), loggerType);
+ }
+
+ @Override
+ @Deprecated
+ public L getLogger(Bundle bundle, String name, Class loggerType) {
+ return getLogger(getName(), loggerType);
+ }
+
+ @Override
+ public boolean isTraceEnabled() {
+ return false;
+ }
+
+ @Override
+ public void trace(String message) {
+ log(new SimpleLogEntry(LogLevel.TRACE, message));
+ }
+
+ @Override
+ public void trace(String format, Object arg) {
+ trace(String.format(format, arg));
+ }
+
+ @Override
+ public void trace(String format, Object arg1, Object arg2) {
+ trace(String.format(format, arg1, arg2));
+ }
+
+ @Override
+ public void trace(String format, Object... arguments) {
+ trace(String.format(format, arguments));
+ }
+
+ @Override
+ @Deprecated
+ public void trace(LoggerConsumer consumer) throws E {
+ throw new UnsupportedOperationException("Logger Consumer currently not supported.");
+ }
+
+ @Override
+ public boolean isDebugEnabled() {
+ return false;
+ }
+
+ @Override
+ public void debug(String message) {
+ log(new SimpleLogEntry(LogLevel.DEBUG, message));
+ }
+
+ @Override
+ public void debug(String format, Object arg) {
+ debug(String.format(format, arg));
+ }
+
+ @Override
+ public void debug(String format, Object arg1, Object arg2) {
+ debug(String.format(format, arg1, arg2));
+ }
+
+ @Override
+ public void debug(String format, Object... arguments) {
+ trace(String.format(format, arguments));
+ }
+
+ @Override
+ @Deprecated
+ public void debug(LoggerConsumer consumer) throws E {
+ throw new UnsupportedOperationException("Logger Consumer currently not supported.");
+ }
+
+ @Override
+ public boolean isInfoEnabled() {
+ return false;
+ }
+
+ @Override
+ public void info(String message) {
+ log(new SimpleLogEntry(LogLevel.INFO, message));
+ }
+
+ @Override
+ public void info(String format, Object arg) {
+ info(String.format(format, arg));
+ }
+
+ @Override
+ public void info(String format, Object arg1, Object arg2) {
+ info(String.format(format, arg1, arg2));
+ }
+
+ @Override
+ public void info(String format, Object... arguments) {
+ info(String.format(format, arguments));
+ }
+
+ @Override
+ @Deprecated
+ public void info(LoggerConsumer consumer) throws E {
+ throw new UnsupportedOperationException("Logger Consumer currently not supported.");
+ }
+
+ @Override
+ public boolean isWarnEnabled() {
+ return true;
+ }
+
+ @Override
+ public void warn(String message) {
+ log(new SimpleLogEntry(LogLevel.WARN, message));
+ }
+
+ @Override
+ public void warn(String format, Object arg) {
+ warn(String.format(format, arg));
+ }
+
+ @Override
+ public void warn(String format, Object arg1, Object arg2) {
+ warn(String.format(format, arg1, arg2));
+ }
+
+ @Override
+ public void warn(String format, Object... arguments) {
+ warn(String.format(format, arguments));
+ }
+
+ @Override
+ @Deprecated
+ public void warn(LoggerConsumer consumer) throws E {
+ throw new UnsupportedOperationException("Logger Consumer currently not supported.");
+ }
+
+ @Override
+ public boolean isErrorEnabled() {
+ return true;
+ }
+
+ @Override
+ public void error(String message) {
+ log(new SimpleLogEntry(LogLevel.ERROR, message));
+ }
+
+ @Override
+ public void error(String format, Object arg) {
+ error(String.format(format, arg));
+ }
+
+ @Override
+ public void error(String format, Object arg1, Object arg2) {
+ error(String.format(format, arg1, arg2));
+ }
+
+ @Override
+ public void error(String format, Object... arguments) {
+ error(String.format(format, arguments));
+ }
+
+ @Override
+ @Deprecated
+ public void error(LoggerConsumer consumer) throws E {
+ throw new UnsupportedOperationException("Logger Consumer currently not supported.");
+ }
+
+ @Override
+ public void audit(String message) {
+ log(new SimpleLogEntry(LogLevel.AUDIT, message));
+ }
+
+ @Override
+ public void audit(String format, Object arg) {
+ audit(String.format(format, arg));
+ }
+
+ @Override
+ public void audit(String format, Object arg1, Object arg2) {
+ audit(String.format(format, arg1, arg2));
+ }
+
+ @Override
+ public void audit(String format, Object... arguments) {
+ audit(String.format(format, arguments));
+ }
+
+ public static class SimpleLogEntry implements LogEntry {
+
+ private final LogLevel level;
+ private final String message;
+ private final Optional execption;
+
+ public SimpleLogEntry(LogLevel level, String message) {
+ this(level, message, Optional.empty());
+ }
+
+ public SimpleLogEntry(LogLevel level, String message, Throwable execption) {
+ this(level, message, Optional.of(execption));
+ }
+
+ private SimpleLogEntry(LogLevel level, String message, Optional execption) {
+ this.level = level;
+ this.message = message;
+ this.execption = execption;
+ }
+
+ @Override
+ public Bundle getBundle() {
+ //Return the spotless framework bundle
+ return InternalPlatform.getDefault().getBundleContext().getBundle();
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ @Override
+ public ServiceReference getServiceReference() {
+ return null;
+ }
+
+ @Override
+ @Deprecated
+ //Backward compatibility with Eclipse OSGI 3.12
+ public int getLevel() {
+ switch (level) {
+ case DEBUG:
+ case TRACE:
+ return LogService.LOG_DEBUG;
+ case AUDIT:
+ case INFO:
+ return LogService.LOG_INFO;
+ case ERROR:
+ return LogService.LOG_ERROR;
+ case WARN:
+ return LogService.LOG_WARNING;
+ }
+ return LogService.LOG_ERROR; //Don't fail here. Just log it as error. This is anyway just for debugging internal problems.
+ }
+
+ @Override
+ public String getMessage() {
+ return message;
+ }
+
+ @Override
+ public Throwable getException() {
+ return execption.orElse(null);
+ }
+
+ @Override
+ public long getTime() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ StringWriter result = new StringWriter();
+ result.write(message);
+ if (execption.isPresent()) {
+ result.write('\n');
+ result.write(execption.get().toString());
+ result.write('\n');
+ execption.get().printStackTrace(new PrintWriter(result));
+ }
+ return result.toString();
+ }
+
+ @Override
+ public LogLevel getLogLevel() {
+ return level;
+ }
+
+ @Override
+ public String getLoggerName() {
+ return this.getClass().getSimpleName();
+ }
+
+ @Override
+ public long getSequence() {
+ return 0;
+ }
+
+ @Override
+ public String getThreadInfo() {
+ return null;
+ }
+
+ @Override
+ public StackTraceElement getLocation() {
+ return null;
+ }
+
+ }
+
+}
diff --git a/_ext/eclipse-groovy/src/test/java/com/diffplug/spotless/extra/eclipse/groovy/GrEclipseFormatterStepImplTest.java b/_ext/eclipse-groovy/src/test/java/com/diffplug/spotless/extra/eclipse/groovy/GrEclipseFormatterStepImplTest.java
new file mode 100644
index 0000000000..aaf26a8352
--- /dev/null
+++ b/_ext/eclipse-groovy/src/test/java/com/diffplug/spotless/extra/eclipse/groovy/GrEclipseFormatterStepImplTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2016 DiffPlug
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.diffplug.spotless.extra.eclipse.groovy;
+
+import static com.diffplug.spotless.extra.eclipse.groovy.GrEclipseFormatterStepImpl.IGNORE_FORMATTER_PROBLEMS;
+import static org.codehaus.groovy.eclipse.refactoring.PreferenceConstants.*;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Properties;
+import java.util.function.Consumer;
+
+import org.eclipse.jdt.core.JavaCore;
+import org.junit.Test;
+
+/** Smoke test checking that transitive dependencies are complete. */
+public class GrEclipseFormatterStepImplTest {
+
+ private final static TestData TEST_DATA = TestData.getTestDataOnFileSystem();
+ private final static String PARSER_EXCEPTION = "class Test { void method() {} ";
+ private final static String SCANNER_EXCEPTION = "{";
+ private final static String BOUNDED_WILDCARDS = "foo(Map e) {}";
+
+ @Test
+ public void defaultFormat() throws Throwable {
+ String output = format(TEST_DATA.input("nominal.test"), config -> {});
+ assertEquals("Unexpected default formatting.",
+ TEST_DATA.expected("nominal.test"), output);
+ }
+
+ @Test
+ public void validConfiguration() throws Throwable {
+ String output = format(TEST_DATA.input("nominal.test"), config -> {
+ config.put(GROOVY_FORMATTER_REMOVE_UNNECESSARY_SEMICOLONS, "true");
+ });
+ assertEquals("Unexpected formatting fro custom configuration.",
+ TEST_DATA.expected("nominal.test").replace(";", ""), output);
+ }
+
+ @Test
+ public void invalidConfiguration() throws Throwable {
+ String output = format(TEST_DATA.input("nominal.test"), config -> {
+ config.put(GROOVY_FORMATTER_INDENTATION, JavaCore.SPACE);
+ config.put(GROOVY_FORMATTER_INDENTATION_SIZE, "noInteger");
+ });
+ assertEquals("Groovy formatter does not replace invalid preferences by their defaults.",
+ TEST_DATA.expected("nominal.test").replace("\t", " "), output);
+ }
+
+ /** Test the handling AntlrParserPlugin exceptions by GroovyLogManager.manager logging */
+ @Test(expected = IllegalArgumentException.class)
+ public void parserException() throws Throwable {
+ format(PARSER_EXCEPTION, config -> {});
+ }
+
+ /** Test the handling GroovyDocumentScanner exceptions by GroovyCore logging */
+ @Test(expected = IllegalArgumentException.class)
+ public void scannerException() throws Throwable {
+ format(SCANNER_EXCEPTION, config -> {});
+ }
+
+ /** Test the handling bounded wildcards templates */
+ @Test(expected = IllegalArgumentException.class)
+ public void boundedWildCards() throws Throwable {
+ format(BOUNDED_WILDCARDS, config -> {});
+ }
+
+ @Test
+ public void ignoreCompilerProblems() throws Throwable {
+ Consumer ignoreCompilerProblems = config -> {
+ config.setProperty(IGNORE_FORMATTER_PROBLEMS, "true");
+ };
+ format(PARSER_EXCEPTION, ignoreCompilerProblems);
+ format(SCANNER_EXCEPTION, ignoreCompilerProblems);
+ format(BOUNDED_WILDCARDS, ignoreCompilerProblems);
+ //Test is passed if it does not throw an exception. See issue 237.
+ }
+
+ private static String format(final String input, final Consumer config) throws Exception {
+ Properties properties = new Properties();
+ config.accept(properties);
+ GrEclipseFormatterStepImpl formatter = new GrEclipseFormatterStepImpl(properties);
+ return formatter.format(input);
+ }
+
+}
diff --git a/_ext/eclipse-groovy/src/test/java/com/diffplug/spotless/extra/eclipse/groovy/TestData.java b/_ext/eclipse-groovy/src/test/java/com/diffplug/spotless/extra/eclipse/groovy/TestData.java
new file mode 100644
index 0000000000..5fc8bb4571
--- /dev/null
+++ b/_ext/eclipse-groovy/src/test/java/com/diffplug/spotless/extra/eclipse/groovy/TestData.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016 DiffPlug
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.diffplug.spotless.extra.eclipse.groovy;
+/*
+ * Copyright 2016 DiffPlug
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class TestData {
+ public static TestData getTestDataOnFileSystem() {
+ final String userDir = System.getProperty("user.dir", ".");
+ Path dataPath = Paths.get(userDir, "src", "test", "resources");
+ if (Files.isDirectory(dataPath)) {
+ return new TestData(dataPath);
+ }
+ return null;
+ }
+
+ private final Path inputPath;
+ private final Path expectedPath;
+
+ private TestData(Path dataPath) {
+ inputPath = dataPath.resolve("input").toAbsolutePath();
+ expectedPath = dataPath.resolve("expected").toAbsolutePath();
+ for (Path testDataDir : new Path[]{inputPath, expectedPath}) {
+ if (!Files.isDirectory(testDataDir)) {
+ throw new IllegalArgumentException(String.format("'%1$s' is not a directory.", testDataDir));
+ }
+ }
+ }
+
+ public String input(final String fileName) throws Exception {
+ return read(inputPath.resolve(fileName));
+ }
+
+ public String expected(final String fileName) {
+ Path path = expectedPath.resolve(fileName);
+ return read(path);
+ }
+
+ private String read(final Path xmlPath) {
+ if (!Files.isRegularFile(xmlPath)) {
+ throw new IllegalArgumentException(String.format("'%1$s' is not a regular file.", xmlPath));
+ }
+ try {
+ String checkedOutFileContent = new String(java.nio.file.Files.readAllBytes(xmlPath), "UTF8");
+ return checkedOutFileContent.replace("\r", ""); //Align GIT end-of-line normalization
+ } catch (IOException e) {
+ throw new IllegalArgumentException(String.format("Failed to read '%1$s'.", xmlPath), e);
+ }
+ }
+
+}
diff --git a/_ext/eclipse-groovy/src/test/resources/expected/nominal.test b/_ext/eclipse-groovy/src/test/resources/expected/nominal.test
new file mode 100644
index 0000000000..a40d247bad
--- /dev/null
+++ b/_ext/eclipse-groovy/src/test/resources/expected/nominal.test
@@ -0,0 +1,13 @@
+class TestClass {
+ def a;
+
+ TestClass(String s) {
+ this.a = s
+ }
+ def methodNamedArgs(Map args) {
+ "named args: $args"
+ }
+}
+
+def t = new TestClass()
+def arr = [4, 'string1', 'string2']
diff --git a/_ext/eclipse-groovy/src/test/resources/input/nominal.test b/_ext/eclipse-groovy/src/test/resources/input/nominal.test
new file mode 100644
index 0000000000..85f742677f
--- /dev/null
+++ b/_ext/eclipse-groovy/src/test/resources/input/nominal.test
@@ -0,0 +1,15 @@
+class TestClass {
+ def a;
+
+TestClass(String s) {
+this.a = s
+}
+ def methodNamedArgs(Map args) {
+ "named args: $args"
+ }
+}
+
+def t = new TestClass()
+def arr = [4,
+'string1',
+'string2']
diff --git a/_ext/gradle/java-setup.gradle b/_ext/gradle/java-setup.gradle
index ea5e5dc1f6..96a56e3d50 100644
--- a/_ext/gradle/java-setup.gradle
+++ b/_ext/gradle/java-setup.gradle
@@ -14,7 +14,11 @@ apply plugin: 'java'
sourceCompatibility = ext_VER_JAVA
targetCompatibility = ext_VER_JAVA
-tasks.withType(JavaCompile) { options.encoding = 'UTF-8' }
+tasks.withType(JavaCompile) {
+ options.encoding = 'UTF-8'
+ options.compilerArgs << "-Xlint:unchecked"
+ options.compilerArgs << "-Xlint:deprecation"
+}
// Use file locking
configurations {
diff --git a/_ext/greclipse/README.md b/_ext/greclipse/README.md
deleted file mode 100644
index 99c06e21bb..0000000000
--- a/_ext/greclipse/README.md
+++ /dev/null
@@ -1,41 +0,0 @@
-# spotless-groovy-eclipse
-
-Groovy-Eclipse is not available in a form which can be easily consumed by maven or gradle.
-To fix this, we publish Groovy-Eclipse's formatter and all its dependencies, along with a small amount of glue code, into the `com.diffplug.gradle.spotless:spotless-greclipse` artifact.
-
-## Build
-
-To publish a new version, update the `_ext/greclipse/gradle.properties` appropriately and run this from the root directory:
-
-```
-gradlew -b _ext/greclipse/build.gradle publish
-```
-
-Spotless at large is under the Apache 2.0 license, but this jar is under the EPL v1.
-
-## IDE
-
-For IDE support the JAR dependencies and their sources are downloaded from P2 repositories.
-This can, due to restrictions on server side, take up to half an hour.
-
-
-### Eclipse
-
-Run the `eclipse` task:
-
-```
-gradlew -b _ext/greclipse/build.gradle eclipse
-```
-
-Import the existing general project (NOT the Gradle project) from `_ext/greclipse` into your workspace.
-
-
-### IntelliJ IDEA
-
-Run the `idea` task:
-
-```
-gradlew -b _ext/greclipse/build.gradle idea
-```
-
-Import the project from `_ext/greclipse` using the external Gradle model.
diff --git a/_ext/greclipse/build.gradle b/_ext/greclipse/build.gradle
deleted file mode 100644
index 180a7e9d3c..0000000000
--- a/_ext/greclipse/build.gradle
+++ /dev/null
@@ -1,452 +0,0 @@
-import java.io.File
-
-import org.apache.commons.io.filefilter.DirectoryFileFilter
-
-plugins {
- // bintray uploading
- id 'com.jfrog.bintray' version '1.3.1'
- // p2 dependencies
- id 'com.diffplug.gradle.p2.asmaven' version '3.3.0'
-}
-
-repositories {
- maven { url 'https://plugins.gradle.org/m2/' }
-}
-
-apply plugin: 'java'
-
-///////////////////
-// Configuration //
-///////////////////
-
-// The dependencies to pull from GrEclipse's p2 repositories
-def grEclipseDeps = [
- 'org.codehaus.groovy.eclipse.refactoring':'+', // GroovyFormatter and related
-
- // The following lists does not reflect the complete transitive required packages, but
- // the once used during code formatting
- 'org.codehaus.groovy':'+', // Groovy compiler patches supporting use within GrEclipse and Groovy itself
- 'org.codehaus.groovy.eclipse.core':'+', // Groovy core classes (provides central logging used by formatter)
- 'org.eclipse.jdt.core':"${grec_VER_JDT_PATCH}", // Patches org.eclipse.jdt.core classes supporting use within GrEclipse (provides AST generator)
- 'org.eclipse.jdt.groovy.core':'+' // Extends org.eclipse.jdt.core for Groovy
-]
-
-// The dependencies to pull from Eclipse's p2 repositories
-def eclipseDeps = [
- 'org.eclipse.core.commands':'+', // Event manager required by preference store
- 'org.eclipse.core.contenttype':'+', // Required by JavaCore options
- 'org.eclipse.core.jobs':'+', // Required by JavaCore options
- 'org.eclipse.core.runtime':'+', // Provides central logging interface
- 'org.eclipse.core.resources':'+', // GrEclipse parser checks workspace resources
- 'org.eclipse.equinox.common':'+', // Provides runtime status used during exception reporting
- 'org.eclipse.equinox.preferences':'+', // Preferences used for formatter configuration
- 'org.eclipse.jface':'+', // PreferenceStore for creating preferences from properties
- 'org.eclipse.jface.text':'+', // Only required for ITextSelection (never used for our calls)
- 'org.eclipse.osgi':'+', // GroovyCore accesses OSGI bundle (but not effectively used)
- 'org.eclipse.text':'+' // Provides Document data structure for formatter
-]
-
-ext {
- //Include/Excludes form the JARs, which goes into a fat-jar with the spottless formatter interface.
- jarInclude = [
- '**/*.class', // Take all classes
- '**/*.java', // ... and sources.
- '**/*.properties', // Text resources (for messages, etc)
- '*.html', // License information about the included JARs,
- 'META-INF/**' // Information about the origin of the individual class files
- ]
- jarExclude = [
- 'META-INF/*.RSA', // The eclipse jars are signed, and our fat-jar breaks the signatures
- 'META-INF/*.SF', // ... so all signatures are filtered
- 'org/codehaus/groovy/eclipse/core/GroovyCoreActivator.*', // Is replaced to use the plugin code without Eclipse
- 'org/codehaus/groovy/antlr/ErrorRecoveredCSTParserPluginFactory.*' // Is replaced to allow parser error handling
- ]
-
- //Some JARs include JARs themselfs
- internalJars = [
- //Jars included by org.codehaus.groovy
- "**/groovy-all-${grec_VER_GROOVY}", // Use Groovy compiler compatible with GrEclipse instead of localGroovy
- "**/groovy-${grec_VER_GROOVY}", // Groovy compiler sources do not follow the same name pattern of groovy-all
- '**/groovy-eclipse', // Patches/Overrides some of the Groovy compiler classes
- '**/eclipse-trace', // Provides logging capabilities for groovy-eclipse
-
- //Jars included by org.eclipse.jdt.groovy.core
- '**/nlcl' //Non locking class loader used by groovy compiler
- ]
-
- // GrEclipse source bundle (not available as dedicated source JARs)
- grEclipseSourceUrl = "https://github.com/groovy/groovy-eclipse/archive/v${grec_VER_GRECLIPSE}.tar.gz"
- grEclipseSourceTgz = project.file("build/greclipse-archive/v${grec_VER_GRECLIPSE}.tar.gz")
- grEclipseSourceDir = project.file('build/greclipse-archive/grEclipseSource')
- // Sources of GrEclipse dependencies for...
- verGroovySource = grec_VER_GROOVY.substring(0, grec_VER_GROOVY.lastIndexOf('.')).replace('.', '')
- grEclipseDepsSource = [
- "base/org.codehaus.groovy${verGroovySource}/src", // org.codehaus.groovy unit
- "base/org.codehaus.groovy${verGroovySource}/src-trace", // eclipse-trace internal JAR
- 'base/org.eclipse.jdt.groovy.core/src', // org.eclipse.jdt.groovy.core unit
- 'ide/org.codehaus.groovy.eclipse.core/src', // org.codehaus.groovy.eclipse.core unit
- 'ide/org.codehaus.groovy.eclipse.refactoring/src', // org.codehaus.groovy.eclipse.refactoring unit
- ]
- //The jdt-patch is organised in sub-modules patching existing code
- jdtPatchDepsSourceDir = new File("${grEclipseSourceDir}/jdt-patch/e${grec_VER_ECLIPSE.replace('.', '')}/org.eclipse.jdt.core")
-
- // The directory contains all external classes for the fat-jar
- embeddedClassesDirName = 'build/embeddedClasses'
- embeddedClassesDir = project.file(embeddedClassesDirName)
-
- // The directory contains all external source files the fat-jar is based on
- embeddedSourcesDirName = 'build/embeddedSources'
- embeddedSourcesDir = project.file(embeddedSourcesDirName)
-
-}
-
-// build a maven repo in our build folder containing these artifacts
-p2AsMaven {
- group 'p2', {
- repoEclipse grec_VER_ECLIPSE
- eclipseDeps.keySet.each { p2.addIU(it) }
- eclipseDeps.keySet.each { p2.addIU(it + '.source') }
- repo "http://dist.springsource.org/release/GRECLIPSE/${grec_VER_GRECLIPSE}/e${grec_VER_ECLIPSE}"
- grEclipseDeps.keySet.each { p2.addIU(it) }
- }
-}
-
-configurations {
- embeddedJars // JARs (Eclipse and GrEclipse) the fat-jar is based uppon
- eclipseSource // Source for Eclipse JARS (GrEclipse provides no source packages)
-}
-
-///////////////////
-// External Deps //
-///////////////////
-
-task grEclipseSource {
- description = 'Download GrEclipse from GitHub archive.'
- inputs.property('url', grEclipseSourceUrl.toString())
- outputs.file(grEclipseSourceDir)
-
- doLast {
- grEclipseSourceDir.deleteDir()
- grEclipseSourceDir.mkdirs()
- ant.get(src: grEclipseSourceUrl, dest: grEclipseSourceTgz, skipexisting: 'true')
- ant.untar(src: grEclipseSourceTgz, dest: grEclipseSourceDir, compression: 'gzip') {
- cutdirsmapper(dirs: '1')
- }
- }
-}
-
-task copyEmbeddedSources(dependsOn: grEclipseSource) {
- description = "Copies filtered set of source files from the Eclise/GrEclipse dependencies to '${project.relativePath(embeddedSourcesDir)}'."
- inputs.files(configurations.eclipseSource)
- inputs.file(grEclipseSourceDir)
- inputs.property('internalJars', internalJars)
- inputs.property('jarInclude', jarInclude)
- inputs.property('jarExclude', jarExclude)
- outputs.file(embeddedSourcesDir)
-
- doLast {
- embeddedSourcesDir.deleteDir()
- embeddedSourcesDir.mkdirs()
- configurations.eclipseSource.each {
- unjar(it, embeddedSourcesDir)
- }
-
- // Incorparate the Eclipse patches/extensions into default source directory structure
- copy("${embeddedSourcesDir}/ant_tasks/resources-antsrc", embeddedSourcesDir, 'move')
-
- // Extract source JARs provided with GrEcslipse (for exampel the compiler)
- def jarSourceIncludes = []
- internalJars.each {
- def jarFilter = it
- ['sources', 'source', 'src'].each {
- jarSourceIncludes << "${jarFilter}-${it}.jar"
- }
- }
- def tree = fileTree(dir: grEclipseSourceDir, includes: jarSourceIncludes)
- tree.each {
- unjar(it, embeddedSourcesDir)
- }
-
- grEclipseDepsSource.each {
- copy("${grEclipseSourceDir}/${it}", embeddedSourcesDir)
- }
- //The jdt-patch is organised in sub-modules patching existing code
- jdtPatchDepsSourceDir.list(DirectoryFileFilter.DIRECTORY).each {
- copy("${jdtPatchDepsSourceDir}/${it}", embeddedSourcesDir)
- }
-
- //Clean up empty directories and class files
- ant.delete(includeemptydirs: 'true') {
- fileset(dir: embeddedSourcesDir) {
- or {
- and {
- size(value: '0')
- type(type: 'dir')
- }
- filename(name: '**/*.class')
- filename(name: '*.java')
- }
- }
- }
- }
-
-}
-
-def copy(fromDir, toDir, method='copy') {
- logger.debug("${method} ${fromDir} to ${toDir}")
- ant."$method"(todir: toDir, includeEmptyDirs: 'false', overwrite: 'true') {
- fileset(dir: fromDir) {
- jarInclude.each {
- include(name: "${it}")
- }
- jarExclude.each {
- exclude(name: "${it}")
- }
- }
- }
-}
-
-task unjarEmbeddedClasses {
- description = "Copies filtered set of embedded classes from the Eclise/GrEclipse dependencies to '${project.relativePath(embeddedClassesDir)}'."
- inputs.files(configurations.embeddedJars)
- inputs.property('internalJars', internalJars)
- inputs.property('jarInclude', jarInclude)
- inputs.property('jarExclude', jarExclude)
- outputs.file(embeddedClassesDir)
-
- doLast {
- embeddedClassesDir.deleteDir()
- embeddedClassesDir.mkdirs()
- configurations.embeddedJars.each {
- unjar(it, embeddedClassesDir)
- }
- //Unpack internal JARs. Maintain the order defined in internalJars
- internalJars.each {
- fileTree(embeddedClassesDir).include("${it}.jar").each {
- unjar(it, embeddedClassesDir)
- delete(it)
- }
- }
- }
-}
-
-def unjar(File jarFile, File destDir) {
- ant.unjar(src: jarFile, dest: destDir) {
- patternset {
- jarInclude.each {
- include(name: "${it}")
- }
- internalJars.each {
- include(name: "**/${it}.jar")
- }
- jarExclude.each {
- exclude(name: "${it}")
- }
- }
- }
- //Keep the manifest for transparency
- ant.move(file: "${destDir}/META-INF/MANIFEST.MF", tofile: "${destDir}/META-INF/${jarFile.getName()}-MANIFEST.MF", quiet: 'true', failonerror: 'false')
- //Keep licenses and other human readable information for transparency
- ant.move(todir: destDir, quiet: 'true') {
- fileset(dir: destDir) {
- include(name: '*')
- type(type: 'file')
- exclude(name: '*jar-*')
- exclude(name: '*.jar')
- }
- mapper(type: 'glob', from: '*', to: "${jarFile.getName()}-*")
- }
-}
-
-
-/////////////
-// Compile //
-/////////////
-
-dependencies {
- // Add the Eclipse and GrEclipse jars to the embedded configuration.
- eclipseDeps.each { groupArtifact, version ->
- embeddedJars "p2:${groupArtifact}:${version}"
- eclipseSource "p2:${groupArtifact}:${version}:sources"
- }
- // Some grEclipseDeps classes patch/override the eclipseDeps once. Hence grEclipseDeps
- // must added to embeddedJars after eclipseDeps.
- grEclipseDeps.each { groupArtifact, version ->
- embeddedJars "p2:${groupArtifact}:${version}"
- }
-
- // The resulting fat-jar will have no transitive dependencies itself.
- compile files(embeddedClassesDir)
-
- // testing
- testCompile "junit:junit:${grec_VER_JUNIT}"
-}
-
-tasks.compileJava.dependsOn(unjarEmbeddedClasses)
-
-
-/////////
-// IDE //
-/////////
-
-apply plugin: 'eclipse'
-
-eclipse {
- classpath {
- downloadSources true
- downloadJavadoc true
- file {
- withXml { xmlProvider ->
- def classpathNode = xmlProvider.asNode()
- def embeddedClassesPath = embeddedClassesDir.absolutePath
- def embeddedNode = classpathNode.find { it.@path == embeddedClassesPath }
- embeddedNode.@sourcepath = embeddedSourcesDir
- }
- }
- }
-}
-
-// always create fresh projects
-tasks.eclipse.dependsOn(cleanEclipse)
-// Encure that the dependent classes and sources are preovided for compilation if project is build via Eclipse instead of command line
-tasks.eclipseClasspath.dependsOn(unjarEmbeddedClasses, copyEmbeddedSources)
-
-apply plugin: 'idea'
-
-// Encure that the dependent classes and sources are preovided for compilation if project is build via Eclipse instead of command line
-tasks.idea.dependsOn(unjarEmbeddedClasses, copyEmbeddedSources)
-
-
-tasks.idea.doLast {
- def ideaEmbeddedLibTableFile = project.file('.idea/libraries/embeddedClasses.xml')
- def ideaEmbeddedLibTableDir = ideaEmbeddedLibTableFile.parentFile
- ideaEmbeddedLibTableDir.parentFile.mkdir()
- ideaEmbeddedLibTableDir.mkdir()
- ideaEmbeddedLibTableFile.delete()
- ideaEmbeddedLibTableFile << """
-
-
-
-
-
-
-
-
-
-
-
- """
-}
-
-////////////////
-// Publishing //
-////////////////
-apply plugin: 'maven-publish'
-
-jar {
- dependsOn << unjarEmbeddedClasses
- from (embeddedClassesDir)
-}
-
-task sourcesJar(type: Jar, dependsOn: copyEmbeddedSources) {
- classifier = 'sources'
- from ([sourceSets.main.allJava, embeddedSourcesDir])
-}
-
-task javadocJar(type: Jar, dependsOn: javadoc) {
- classifier = 'javadoc'
- from javadoc.destinationDir
-}
-
-def isSnapshot = grec_version.endsWith('-SNAPSHOT')
-// pulls the credentials from either the environment variable or gradle.properties
-def cred = {
- if (System.env[it] != null) {
- return System.env[it]
- } else if (project.hasProperty(it)) {
- return project[it]
- } else {
- return 'unknown_' + it
- }
-}
-
-model {
- publishing {
- publications {
- mavenJava(MavenPublication) {
- artifact jar
- artifact sourcesJar
- artifact javadocJar
-
- groupId project.grec_group
- artifactId project.grec_artifactId
- version project.grec_version
-
- pom.withXml {
-
- // add MavenCentral requirements to the POM
- asNode().children().last() + {
- resolveStrategy = Closure.DELEGATE_FIRST
- name project.grec_artifactId
- description project.grec_description
- url "https://github.com/${project.grec_org}/${project.name}"
- scm {
- url "https://github.com/${project.grec_org}/${project.name}"
- connection "scm:git:git://github.com/${project.grec_org}/${project.name}"
- developerConnection "scm:git:ssh:git@github.com/${project.grec_org}/${project.name}"
- }
- licenses {
- license {
- name 'Eclipse Public License - v 1.0'
- url 'https://www.eclipse.org/legal/epl-v10.html'
- distribution 'repo'
- }
- }
- developers {
- developer {
- id 'fvgh'
- name 'Frank Vennemeyer'
- email 'frankgh@zoho.com'
- }
- }
- }
- }
- }
- }
- if (isSnapshot) {
- // upload snapshots to oss.sonatype.org
- repositories { maven {
- url = 'https://oss.sonatype.org/content/repositories/snapshots'
- credentials {
- username = cred('nexus_user')
- password = cred('nexus_pass')
- }
- } }
- }
- }
-}
-
-if (!isSnapshot) {
- // upload releases to bintray and then mavenCentral
- bintray {
- user = cred('bintray_user')
- key = cred('bintray_pass')
- publications = ['mavenJava']
- publish = true
- pkg {
- repo = 'opensource'
- name = project.grec_artifactId
- userOrg = project.grec_org
- version {
- name = project.grec_version
- mavenCentralSync {
- user = cred('nexus_user')
- password = cred('nexus_pass')
- }
- }
- }
- }
-
- publish.dependsOn(bintrayUpload)
- bintrayUpload.dependsOn(['generatePomFileForMavenJavaPublication', jar, sourcesJar, javadocJar])
-}
diff --git a/_ext/greclipse/gradle.properties b/_ext/greclipse/gradle.properties
deleted file mode 100644
index dbffb524cd..0000000000
--- a/_ext/greclipse/gradle.properties
+++ /dev/null
@@ -1,17 +0,0 @@
-# Mayor/Minor versions are in line with the Groovy version values.
-# Patch version is an incremental counter for the Spotless plugin.
-grec_version=2.3.0
-grec_artifactId=spotless-ext-greclipse
-grec_description=Groovy Eclipse's formatter bundled for Spotless
-
-grec_org=diffplug
-grec_group=com.diffplug.spotless
-
-# Compile
-grec_VER_ECLIPSE=4.4
-grec_VER_GRECLIPSE=2.9.1
-grec_VER_GROOVY=2.3.7
-grec_VER_JDT_PATCH=3.10.0.xx-201411061335-e44-RELEASE
-
-# Test
-grec_VER_JUNIT=4.12
diff --git a/_ext/greclipse/src/main/java/org/codehaus/groovy/antlr/ErrorRecoveredCSTParserPluginFactory.java b/_ext/greclipse/src/main/java/org/codehaus/groovy/antlr/ErrorRecoveredCSTParserPluginFactory.java
deleted file mode 100644
index d26283015d..0000000000
--- a/_ext/greclipse/src/main/java/org/codehaus/groovy/antlr/ErrorRecoveredCSTParserPluginFactory.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2016 DiffPlug
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.codehaus.groovy.antlr;
-
-import java.util.List;
-
-import org.codehaus.groovy.control.ParserPlugin;
-import org.codehaus.groovy.control.ParserPluginFactory;
-import org.codehaus.groovy.eclipse.core.GroovyCoreActivator;
-import org.eclipse.core.runtime.ILog;
-import org.eclipse.core.runtime.Status;
-
-/**
- * Overrides original class allowing spotless formatter to handle parser errors.
- *
- * Compiler Parser errors in GrEclipse are treated as warnings, directed to the "standard"
- * error output stream, if less than 'groovy.errors.tolerance' are detected.
- * The 'groovy.errors.tolerance' is set to the fixed value 10 by the GrEclipse patch of
- * the original codehaus groovy, which is convenient within Eclipse editor on 'unfinished' code.
- * For Spotless is can be assumed that the plugin is applied after successful compilation.
- * Hence for all compiler errors, it can be assumed that the eclipse-groovy parser is not
- * able to cope with the code and therefore should not alter it.
- * Furthermore, in the default GrEclipse warnings, the source file name is replaced by
- * "Hello.groovy" (see GroovySnippetParser), which is not helpful for a spotless error report.
- *
- * This patch is used as the least intrusive work-around.
- */
-public class ErrorRecoveredCSTParserPluginFactory extends ParserPluginFactory {
-
- @Override
- public ParserPlugin createParserPlugin() {
- return new ErrorRecoveredCSTParserPlugin(new SpotlessCstReporter());
- }
-
- private static class SpotlessCstReporter implements ICSTReporter {
-
- @Override
- public void generatedCST(String fileName, GroovySourceAST ast) {
- //Always called when an AST has been generated. Nothing to do.
- }
-
- @Override
- public void reportErrors(String fileName, @SuppressWarnings("rawtypes") List errors) {
- ILog log = GroovyCoreActivator.getDefault().getLog();
- for (Object error : errors) {
- log.log(new Status(Status.ERROR, GroovyCoreActivator.PLUGIN_ID, error.toString()));
- }
- }
-
- };
-}
diff --git a/_ext/greclipse/src/main/java/org/codehaus/groovy/eclipse/core/GroovyCoreActivator.java b/_ext/greclipse/src/main/java/org/codehaus/groovy/eclipse/core/GroovyCoreActivator.java
deleted file mode 100644
index 4a54531748..0000000000
--- a/_ext/greclipse/src/main/java/org/codehaus/groovy/eclipse/core/GroovyCoreActivator.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright 2016 DiffPlug
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.codehaus.groovy.eclipse.core;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.security.cert.X509Certificate;
-import java.util.Arrays;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.codehaus.groovy.eclipse.GroovyLogManager;
-import org.eclipse.core.runtime.ILog;
-import org.eclipse.core.runtime.ILogListener;
-import org.eclipse.core.runtime.IStatus;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.Version;
-
-/**
- * Overrides original class allowing Spotless to run formatter without activating Eclipse core.
- *
- * Class provides access to central logger as required by GroovyCore.
- * Furthermore GroovyCore requires a OSGI bundle, which is just used for accessing the plug-in id.
- * This class provides a corresponding mock for the bundle.
- */
-public class GroovyCoreActivator {
-
- public static final String PLUGIN_ID = "com.diffplug.gradle.spotless.groovy.eclipse";
-
- private static GroovyCoreActivator INSTANCE = null;
-
- private final ILog logger;
- private final Bundle bundle;
-
- public GroovyCoreActivator() {
- bundle = new MockOsgiBundle();
- logger = new LogAdapter(bundle);
- GroovyLogManager.manager.setUseDefaultLogger(false);
- }
-
- /** Lazy constructor returning the shared activator instance */
- public static GroovyCoreActivator getDefault() {
- if (null == INSTANCE) {
- INSTANCE = new GroovyCoreActivator();
- }
- return INSTANCE;
- }
-
- /** Returns a OSIG bundle mock for GroovyCore, just providing functionality for Groovy error handling */
- public Bundle getBundle() {
- return bundle;
- }
-
- /** Provides Eclipse logger interface without requiring an active Eclipse core */
- public ILog getLog() {
- return logger;
- }
-
- private static class LogAdapter implements ILog {
-
- private final static Integer[] QUIET_SEVERITY_VALUES = new Integer[]{IStatus.CANCEL, IStatus.INFO, IStatus.OK};
- private final static Set QUIET_SEVERITIES = new HashSet(Arrays.asList(QUIET_SEVERITY_VALUES));
-
- private final Set listeners;
- private final Bundle bundle;
-
- public LogAdapter(Bundle bundle) {
- listeners = new HashSet();
- this.bundle = bundle;
- }
-
- @Override
- public void addLogListener(ILogListener arg0) {
- listeners.add(arg0);
- }
-
- @Override
- public Bundle getBundle() {
- return bundle;
- }
-
- @Override
- public void log(IStatus status) {
- for (ILogListener listener : listeners) {
- listener.logging(status, PLUGIN_ID);
- }
- if (QUIET_SEVERITIES.contains(status.getSeverity())) {
- System.out.println(status.getMessage());
- } else {
- System.err.println(status.getMessage());
- }
- }
-
- @Override
- public void removeLogListener(ILogListener arg0) {
- listeners.remove(arg0);
- }
-
- }
-
- private static class MockOsgiBundle implements Bundle {
-
- @Override
- public int compareTo(Bundle arg0) {
- return 0; //Always equal. There is only one bundle
- }
-
- @Override
- public A adapt(Class arg0) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Enumeration findEntries(String arg0, String arg1, boolean arg2) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public BundleContext getBundleContext() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public long getBundleId() {
- return 0;
- }
-
- @Override
- public File getDataFile(String arg0) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public URL getEntry(String arg0) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Enumeration getEntryPaths(String arg0) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Dictionary getHeaders() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Dictionary getHeaders(String arg0) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public long getLastModified() {
- return 0; //No modifications
- }
-
- @Override
- public String getLocation() {
- return PLUGIN_ID;
- }
-
- @Override
- public ServiceReference>[] getRegisteredServices() {
- return new ServiceReference>[0];
- }
-
- @Override
- public URL getResource(String arg0) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Enumeration getResources(String arg0) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public ServiceReference>[] getServicesInUse() {
- return new ServiceReference>[0];
- }
-
- @Override
- public Map> getSignerCertificates(int arg0) {
- return new HashMap>();
- }
-
- @Override
- public int getState() {
- return Bundle.ACTIVE;
- }
-
- @Override
- public String getSymbolicName() {
- return PLUGIN_ID;
- }
-
- @Override
- public Version getVersion() {
- return new Version(0, 0, 0);
- }
-
- @Override
- public boolean hasPermission(Object arg0) {
- return true;
- }
-
- @Override
- public Class> loadClass(String arg0) throws ClassNotFoundException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void start() throws BundleException {
- //Nothing to do
- }
-
- @Override
- public void start(int arg0) throws BundleException {
- //Nothing to do
- }
-
- @Override
- public void stop() throws BundleException {
- //Nothing to do
- }
-
- @Override
- public void stop(int arg0) throws BundleException {
- //Nothing to do
- }
-
- @Override
- public void uninstall() throws BundleException {
- //Nothing to do
- }
-
- @Override
- public void update() throws BundleException {
- //Nothing to do
- }
-
- @Override
- public void update(InputStream arg0) throws BundleException {
- //Nothing to do
- }
-
- }
-
-}
diff --git a/_ext/greclipse/src/test/java/com/diffplug/gradle/spotless/groovy/eclipse/GrEclipseFormatterStepImplTest.java b/_ext/greclipse/src/test/java/com/diffplug/gradle/spotless/groovy/eclipse/GrEclipseFormatterStepImplTest.java
deleted file mode 100644
index c60605fc74..0000000000
--- a/_ext/greclipse/src/test/java/com/diffplug/gradle/spotless/groovy/eclipse/GrEclipseFormatterStepImplTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2016 DiffPlug
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.diffplug.gradle.spotless.groovy.eclipse;
-
-import static org.junit.Assert.assertTrue;
-
-import java.util.Properties;
-
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/** Smoke test checking that transitive dependencies are complete. */
-public class GrEclipseFormatterStepImplTest {
-
- private final static String INPUT = "class Test { void method() {} }";
- private final static String OUTPUT = "class Test {\n\tvoid method() {}\n}";
- private final static String PARSER_EXCEPTION = "class Test { void method() {} ";
- private final static String SCANNER_EXCEPTION = "{";
- private static GrEclipseFormatterStepImpl FORMATTER = null;
-
- @BeforeClass
- public static void initializeTestData() throws Exception {
- FORMATTER = new GrEclipseFormatterStepImpl(new Properties());
- }
-
- /**
- * Test nominal scenario
- * @throws Throwable No exception is expected
- */
- @Test
- public void formatDefault() throws Throwable {
- String output = FORMATTER.format(INPUT);
- assertTrue(output.equals(OUTPUT));
- }
-
- /**
- * Test the handling AntlrParserPlugin exceptions by SpotlessCstReporter logging
- * @throws Throwable IllegalArgumentException is expected
- */
- @Test(expected = IllegalArgumentException.class)
- public void parserException() throws Throwable {
- FORMATTER.format(PARSER_EXCEPTION);
- }
-
- /**
- * Test the handling GroovyDocumentScanner exceptions by GroovyCore logging
- * @throws Throwable IllegalArgumentException is expected
- */
- @Test(expected = IllegalArgumentException.class)
- public void scannerException() throws Throwable {
- FORMATTER.format(SCANNER_EXCEPTION);
- }
-
-}