Skip to content

Commit

Permalink
XML Extension (#293)
Browse files Browse the repository at this point in the history
XML extension for Gradle and Maven.
  • Loading branch information
fvgh authored Sep 15, 2018
1 parent c00d1cc commit 8818804
Show file tree
Hide file tree
Showing 42 changed files with 1,285 additions and 920 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ lib('kotlin.KtLintStep') +'{{yes}} | {{yes}}
lib('markdown.FreshMarkStep') +'{{yes}} | {{no}} | {{no}} |',
lib('scala.ScalaFmtStep') +'{{yes}} | {{yes}} | {{no}} |',
lib('sql.DBeaverSQLFormatterStep') +'{{yes}} | {{no}} | {{no}} |',
extra('wtp.WtpEclipseFormatterStep') +'{{yes}} | {{yes}} | {{no}} |',
'| [(Your FormatterStep here)](CONTRIBUTING.md#how-to-add-a-new-formatterstep) | {{no}} | {{no}} | {{no}} |',
'| Fast up-to-date checking | {{yes}} | {{no}} | {{no}} |',
'| Automatic idempotency safeguard | {{yes}} | {{no}} | {{no}} |',
Expand All @@ -72,6 +73,7 @@ lib('sql.DBeaverSQLFormatterStep') +'{{yes}} | {{no}}
| [`markdown.FreshMarkStep`](lib/src/main/java/com/diffplug/spotless/markdown/FreshMarkStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`scala.ScalaFmtStep`](lib/src/main/java/com/diffplug/spotless/scala/ScalaFmtStep.java) | :+1: | :+1: | :white_large_square: |
| [`sql.DBeaverSQLFormatterStep`](lib/src/main/java/com/diffplug/spotless/sql/DBeaverSQLFormatterStep.java) | :+1: | :white_large_square: | :white_large_square: |
| [`wtp.WtpEclipseFormatterStep`](lib-extra/src/main/java/com/diffplug/spotless/extra/wtp/WtpEclipseFormatterStep.java) | :+1: | :+1: | :white_large_square: |
| [(Your FormatterStep here)](CONTRIBUTING.md#how-to-add-a-new-formatterstep) | :white_large_square: | :white_large_square: | :white_large_square: |
| Fast up-to-date checking | :+1: | :white_large_square: | :white_large_square: |
| Automatic idempotency safeguard | :+1: | :white_large_square: | :white_large_square: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,88 +41,88 @@ public static void initializeStatic() throws Exception {

@Test
public void simpleDefaultFormat() throws Throwable {
String output = format(TEST_DATA.input("xml_space.xml"), config -> {});
String output = format(TEST_DATA.input("xml_space.test"), config -> {});
assertEquals("Unexpected formatting with default preferences.",
TEST_DATA.expected("xml_space.xml"), output);
TEST_DATA.expected("xml_space.test"), output);
}

@Test
public void invalidXmlFormat() throws Throwable {
String[] input = TEST_DATA.input("xml_space.xml");
String[] input = TEST_DATA.input("xml_space.test");
input[0] += INCOMPLETE;
String output = format(input, config -> {});
String expected = TEST_DATA.expected("xml_space.xml") + LINE_DELIMITER + INCOMPLETE;
String expected = TEST_DATA.expected("xml_space.test") + LINE_DELIMITER + INCOMPLETE;
assertEquals("Incomplete XML not formatted on best effort basis.",
expected, output);
}

@Test
public void illegalXmlCharater() throws Throwable {
String[] input = TEST_DATA.input("xml_space.xml");
String[] input = TEST_DATA.input("xml_space.test");
input[0] = ILLEGAL_CHAR + input[0];
String output = format(input, config -> {});
String expected = LINE_DELIMITER + LINE_DELIMITER + TEST_DATA.expected("xml_space.xml");
String expected = LINE_DELIMITER + LINE_DELIMITER + TEST_DATA.expected("xml_space.test");
assertEquals("Illegal character not replaced by line delimiter.", expected, output);
}

@Test
public void multipleConfigurations() throws Throwable {
String output = format(TEST_DATA.input("xml_space.xml"), config -> {
String output = format(TEST_DATA.input("xml_space.test"), config -> {
config.setProperty(INDENTATION_SIZE, "2");
config.setProperty(INDENTATION_CHAR, SPACE);
});
String expected = TEST_DATA.expected("xml_space.xml").replace("\t", " ");
String expected = TEST_DATA.expected("xml_space.test").replace("\t", " ");
assertEquals("Custom indentation configuration not applied.", expected, output);

output = format(TEST_DATA.input("xml_space.xml"), config -> {
output = format(TEST_DATA.input("xml_space.test"), config -> {
config.setProperty(SPLIT_MULTI_ATTRS, Boolean.toString(true));
});
expected = TEST_DATA.expected("xml_space.xml");
expected = TEST_DATA.expected("xml_space.test");
expected = expected.replace(" a=", LINE_DELIMITER + "\ta=");
expected = expected.replace(" b=", LINE_DELIMITER + "\tb=");
assertEquals("Custom indentation configuration not reverted or custom multiple argument configuration not applied.", expected, output);
}

@Test
public void invalidConfiguration() throws Throwable {
String output = format(TEST_DATA.input("xml_space.xml"), config -> {
String output = format(TEST_DATA.input("xml_space.test"), config -> {
config.setProperty(INDENTATION_SIZE, "Not an integer");
config.setProperty(INDENTATION_CHAR, SPACE);
});
assertEquals("Invalid indentation configuration not replaced by default value (0 spaces)",
TEST_DATA.expected("xml_space.xml").replace("\t", ""), output);
TEST_DATA.expected("xml_space.test").replace("\t", ""), output);
}

@Test
public void dtdRelativePath() throws Throwable {
String output = format(TEST_DATA.input("dtd_relative.xml"), config -> {});
String output = format(TEST_DATA.input("dtd_relative.test"), config -> {});
assertEquals("Relative DTD not resolved. Restrictions are not applied by formatter.",
TEST_DATA.expected("dtd_relative.xml"), output);
TEST_DATA.expected("dtd_relative.test"), output);
}

@Test
public void xsdRelativePath() throws Throwable {
String output = format(TEST_DATA.input("xsd_relative.xml"), config -> {});
String output = format(TEST_DATA.input("xsd_relative.test"), config -> {});
assertEquals("Relative XSD not resolved. Restrictions are not applied by formatter.",
TEST_DATA.expected("xsd_relative.xml"), output);
TEST_DATA.expected("xsd_relative.test"), output);
}

@Test
public void xsdNotFound() throws Throwable {
String output = format(TEST_DATA.input("xsd_not_found.xml"), config -> {});
String output = format(TEST_DATA.input("xsd_not_found.test"), config -> {});
assertEquals("Unresolved XSD/DTD not silently ignored.",
TEST_DATA.expected("xsd_not_found.xml"), output);
TEST_DATA.expected("xsd_not_found.test"), output);
}

@Test
public void catalogLookup() throws Throwable {
String output = format(TEST_DATA.input("xsd_not_found.xml"), config -> {
String output = format(TEST_DATA.input("xsd_not_found.test"), config -> {
config.setProperty(
SpotlessPreferences.USER_CATALOG,
TEST_DATA.getRestrictionsPath("catalog.xml").toString());
});
assertEquals("XSD not resolved by catalog. Restrictions are not applied by formatter.",
TEST_DATA.expected("xsd_not_found.xml").replace(" remove spaces ", "remove spaces"), output);
TEST_DATA.expected("xsd_not_found.test").replace(" remove spaces ", "remove spaces"), output);
}

private static String format(final String[] input, final Consumer<Properties> config) throws Exception {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<!-- OASIS: If the catalog entry file is specified with a relative URI, it is relative to the base URI of the document that contains the processing instruction. -->
<system systemId="http://foo.bar/test.xsd" uri="./test.xsd"/>
<!-- OASIS: If the catalog entry file is specified with a relative URI, it is relative to the base URI of the document that contains the processing instruction. -->
<system systemId="http://foo.bar/test.xsd" uri="./test.xsd" />
</catalog>
6 changes: 3 additions & 3 deletions _ext/eclipse-wtp/src/test/resources/xml/restrictions/test.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
<xs:element name="x">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse"/>
<xs:whiteSpace value="collapse" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:element>
<xs:element name="y">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:whiteSpace value="preserve"/>
<xs:whiteSpace value="preserve" />
</xs:restriction>
</xs:simpleType>
</xs:element>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
import com.diffplug.spotless.extra.EclipseBasedStepBuilder;

/** Formatter step which calls out to the Groovy-Eclipse formatter. */
public final class WtpEclipseFormatterStep {
public final class EclipseWtpFormatterStep {
// prevent direct instantiation
private WtpEclipseFormatterStep() {}
private EclipseWtpFormatterStep() {}

private static final String NAME = "eclipse wtp formatters";
private static final String FORMATTER_PACKAGE = "com.diffplug.spotless.extra.eclipse.wtp.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,18 @@ private enum WTP {
// @formatter:off
CSS( "body {\na: v; b: \nv;\n} \n",
"body {\n\ta: v;\n\tb: v;\n}",
WtpEclipseFormatterStep::createCssBuilder),
EclipseWtpFormatterStep::createCssBuilder),
HTML( "<!DOCTYPE html> <html>\t<head> <meta charset=\"UTF-8\"></head>\n</html> ",
"<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n</head>\n</html>\n",
WtpEclipseFormatterStep::createHtmlBuilder),
EclipseWtpFormatterStep::createHtmlBuilder),
JS( "function f( ) {\na.b(1,\n2);}",
"function f() {\n a.b(1, 2);\n}",
WtpEclipseFormatterStep::createJsBuilder),
EclipseWtpFormatterStep::createJsBuilder),
JSON( "{\"a\": \"b\", \"c\": { \"d\": \"e\",\"f\": \"g\"}}",
"{\n\t\"a\": \"b\",\n\t\"c\": {\n\t\t\"d\": \"e\",\n\t\t\"f\": \"g\"\n\t}\n}",
WtpEclipseFormatterStep::createJsonBuilder),
EclipseWtpFormatterStep::createJsonBuilder),
XML( "<a><b> c</b></a>", "<a>\n\t<b> c</b>\n</a>",
WtpEclipseFormatterStep::createXmlBuilder);
EclipseWtpFormatterStep::createXmlBuilder);
// @formatter:on

public final String input;
Expand Down Expand Up @@ -132,7 +132,7 @@ private FormatterStep createStepForDefaultVersion(Consumer<Properties> config) t
OutputStream tempOut = new FileOutputStream(tempFile);
configProps.store(tempOut, "test properties");
EclipseBasedStepBuilder builder = wtp.builderMethod.apply(TestProvisioner.mavenCentral());
builder.setVersion(WtpEclipseFormatterStep.defaultVersion());
builder.setVersion(EclipseWtpFormatterStep.defaultVersion());
builder.setPreferences(Arrays.asList(tempFile));
return builder.build();
}
Expand Down
5 changes: 5 additions & 0 deletions lib/src/main/java/com/diffplug/spotless/cpp/CppDefaults.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ public class CppDefaults {
//Prevent instantiation
private CppDefaults() {};

/** Filtering based on Eclipse-CDT <code>org.eclipse.core.contenttype.contentTypes</code> */
/**
* Filter based on Eclipse-CDT <code>org.eclipse.core.contenttype.contentTypes</code>
* extension <code>cSource</code>, <code>cHeader</code>, <code>cxxSource</code> and <code>cxxHeader</code>.
*/
public static final List<String> FILE_FILTER = Collections.unmodifiableList(
Arrays.asList("c", "h", "C", "cpp", "cxx", "cc", "c++", "h", "hpp", "hh", "hxx", "inc")
.stream().map(s -> {
Expand Down
38 changes: 38 additions & 0 deletions lib/src/main/java/com/diffplug/spotless/xml/XmlDefaults.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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.xml;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/** Common utilities for XML */
public class XmlDefaults {
//Prevent instantiation
private XmlDefaults() {};

/**
* Filter based on Eclipse-WTP <code>org.eclipse.core.contenttype.contentTypes</code>
* extension <code>org.eclipse.wst.xml.core.xmlsource</code>
*/
public static final List<String> FILE_FILTER = Collections.unmodifiableList(
Arrays.asList("xml", "xsl", "xslt", "wsdl", "xsd", "exsd", "xmi")
.stream().map(s -> "**/*." + s).collect(Collectors.toList()));

/** Delimiter covers beginning of elements and processing instructions. */
public static final String DELIMITER_EXPR = "\\<[a-zA-Z\\?]";
}
7 changes: 7 additions & 0 deletions lib/src/main/java/com/diffplug/spotless/xml/package-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@ParametersAreNonnullByDefault
@ReturnValuesAreNonnullByDefault
package com.diffplug.spotless.xml;

import javax.annotation.ParametersAreNonnullByDefault;

import com.diffplug.spotless.annotations.ReturnValuesAreNonnullByDefault;
1 change: 1 addition & 0 deletions plugin-gradle/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

### Version 3.15.0-SNAPSHOT - TBD ([javadoc](https://diffplug.github.io/spotless/javadoc/snapshot/), [snapshot](https://oss.sonatype.org/content/repositories/snapshots/com/diffplug/spotless/spotless-plugin-gradle/))

* Added `xml` support ([#140](https://github.com/diffplug/spotless/issues/140)) using formatter of Eclipse WTP 3.9.5 ([#241](https://github.com/diffplug/spotless/pull/241)).
* Added C/C++ support using formatter of Eclipse CDT 9.4.3 ([#232](https://github.com/diffplug/spotless/issues/232)).
* Updated default groovy-eclipse from 4.8.0 to 4.8.1 ([#288](https://github.com/diffplug/spotless/pull/288)). New version is based on [Groovy-Eclipse 3.0.0](https://github.com/groovy/groovy-eclipse/wiki/3.0.0-Release-Notes).
* LicenseHeaderStep now wont attempt to add license to `module-info.java` ([#272](https://github.com/diffplug/spotless/pull/272)).
Expand Down
27 changes: 27 additions & 0 deletions plugin-gradle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Spotless can check and apply formatting to any plain-text file, using simple rul

* Eclipse's [CDT](#eclipse-cdt) C/C++ code formatter
* Eclipse's java code formatter (including style and import ordering)
* Eclipse's [WTP-XML](#eclipse-wtp-xml) XML code formatter
* Google's [google-java-format](https://github.com/google/google-java-format)
* [Groovy Eclipse](#groovy-eclipse)'s groovy code formatter
* [FreshMark](https://github.com/diffplug/freshmark) (markdown with variables)
Expand Down Expand Up @@ -317,6 +318,32 @@ spotless {

Use the Eclipse to define the *Code Style preferences* (see [Eclipse documentation](https://www.eclipse.org/documentation/)). Within the preferences *Edit...* dialog, you can export your configuration as XML file, which can be used as a `configFile`. If no `configFile` is provided, the CDT default configuration is used.

<a name="xml-wtp"></a>

## Applying to XML sources

```gradle
spotless {
xml {
target '**/*.xml' // Change file filter. By default files with 'xml', 'xsl', 'xslt', 'wsdl', 'xsd', 'exsd' and 'xmi' extension are supported
eclipse().configFile './xml-formatter.prefs' // Properties file of the Eclipse WTP formatter
// Use for example eclipse('4.7.3a') to specify a specific version of Eclipse,
// available versions are: https://github.com/diffplug/spotless/tree/master/lib-extra/src/main/resources/com/diffplug/spotless/extra/eclipse_wtp_formatters
// also supports license headers
licenseHeader '<!-- Licensed under Apache-2.0 -->' // License header
licenseHeaderFile './license.txt' // License header file
}
}
```

<a name="eclipse-wtp-xml"></a>

### Eclipse [WTP](https://www.eclipse.org/webtools/) XML formatter
Use Eclipse to define the *XML editor preferences* (see [Eclipse documentation](https://www.eclipse.org/documentation/)). The preferences are stored below your Eclipse workspace directory in `.metadata/.plugins/org.eclipse.core.runtime/org.eclipse.wst.xml.core.prefs`. Note that only the differences to the default configuration are stored within the file. Omit the 'configFile' entirely to use the default Eclipse configuration.

The Eclipse WTP formatter supports DTD/XSD restrictions on white spaces. For XSD/DTD lookup, relative and absolute XSD/DTD URIs are supported. Furthermore a user catalog can be configured using the `userCatalog` property key. Add the property to the preference file or add an additional preference or properties files as an additional argument to the `configFile`.


<a name="license-header"></a>

## License header options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,13 @@ public void configFile(Object... configFiles) {

}

/** If the user hasn't specified the files yet, we'll assume he/she means all of the C/C++ files. */
@Override
protected void setupTask(SpotlessTask task) {
if (target == null) {
/*
* The org.gradle.language.c and org.gradle.language.cpp source sets are seldom used.
* Most Gradle C/C++ use external CMake builds (so the source location is unknown to Gradle).
* Hence file extension based filtering is used in line with the org.eclipse.core.contenttype.contentTypes
* Hence file extension based filtering is used in line with the org.eclipse.core.contenttype.contentTypes<
* defined by the CDT plugin.
*/
target(CppDefaults.FILE_FILTER.toArray());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ public void sql(Action<SqlExtension> closure) {
configure(SqlExtension.NAME, SqlExtension.class, closure);
}

/** Configures the special xml-specific extension for XML/XSL/... files (XHTML is excluded). */
public void xml(Action<XmlExtension> closure) {
configure(XmlExtension.NAME, XmlExtension.class, closure);
}

/** Configures the special C/C++-specific extension. */
public void cpp(Action<CppExtension> closure) {
configure(CppExtension.NAME, CppExtension.class, closure);
Expand Down
Loading

0 comments on commit 8818804

Please sign in to comment.