-
Notifications
You must be signed in to change notification settings - Fork 460
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added support for Maven POM sorting/formatting #946
Conversation
Documentation is still missing, would like to know if this is something you want inside spotless, before I do the tedious documentation work. 😄 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be great to add this, but the third-party dep needs to be resolved dynamically via JarState
. If every formatter in lib
and lib-extra
just added itself as a dependency, we would have an absolute nightmare of transitive conflicts, and we would have to publish a new plugin every few days as one or another plugin releases a new version.
lib-extra/build.gradle
Outdated
@@ -16,6 +16,8 @@ dependencies { | |||
implementation "com.googlecode.concurrent-trees:concurrent-trees:2.6.1" | |||
// used for xml parsing in EclipseFormatter | |||
implementation "org.codehaus.groovy:groovy-xml:3.0.9" | |||
// used for pom sorting | |||
implementation 'com.github.ekryd.sortpom:sortpom-sorter:3.0.0' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This dep needs to be resolved like this:
this.jarState = JarState.from(MAVEN_COORDINATE + version, provisioner); |
return input -> { | ||
// SortPom expects a file to sort, so we write the inpout into a temporary file | ||
File pom = File.createTempFile("pom", ".xml"); | ||
pom.deleteOnExit(); | ||
try (FileWriter fw = new FileWriter(pom)) { | ||
fw.write(input); | ||
} | ||
SortPomImpl sortPom = new SortPomImpl(); | ||
sortPom.setup(new SortPomLogger() { | ||
@Override | ||
public void warn(String content) { | ||
logger.warning(content); | ||
} | ||
|
||
@Override | ||
public void info(String content) { | ||
logger.info(content); | ||
} | ||
|
||
@Override | ||
public void error(String content) { | ||
logger.severe(content); | ||
} | ||
}, PluginParameters.builder() | ||
.setPomFile(pom) | ||
.setFileOutput(false, null, null, false) | ||
.setEncoding(encoding) | ||
.setFormatting(lineSeparator, expandEmptyElements, spaceBeforeCloseEmptyElement, keepBlankLines) | ||
.setIndent(nrOfIndentSpace, indentBlankLines, indentSchemaLocation) | ||
.setSortOrder(sortOrderFile, predefinedSortOrder) | ||
.setSortEntities(sortDependencies, sortDependencyExclusions, sortPlugins, sortProperties, sortModules, sortExecutions) | ||
.setTriggers(false) | ||
.build()); | ||
sortPom.sortPom(); | ||
return IOUtils.toString(new FileReader(pom)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And the jar should be called using reflection. You can do it raw as we do for google-java-format,
or it might be worth incorporating some pieces of jOOR to make this easier, or if you're really fluent with Gradle you could do it with #524
14ee011
to
b7958a9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the way that you added a sortPom
sourceSet is great. I don't understand why JarState::getClassLoader
wasn't enough, I don't think you need the serialization tricks nor to make a new kind of classloader. I might be wrong though.
The classloader you already get from JarState is built like so:
.computeIfAbsent(serializedKey, k -> new FeatureClassLoader(state.jarUrls(), this.getClass().getClassLoader())); |
I might be wrong, but I think that you should be able to pass objects from SortPomStep
to SortPomFormatterFunc
without serializing them. This stuff is tricky, and I'm very willing to believe that I'm wrong.
If the serialization stuff really is necessary, then we should either:
- add them as API's onto JarState so that the code inside
SortPomStep
is easy to read, and the serialization boilerplate happens insideJarState
- this would be a bummer, but maybe
FeatureClassLoader
needs to be public API, and the serialization boilerplate can go there.
But ideally it isn't necessary in the first place!
lib/src/sortPom/java/com/diffplug/spotless/pom/DelegatingClassLoader.java
Outdated
Show resolved
Hide resolved
lib/src/sortPom/java/com/diffplug/spotless/pom/SortPomStep.java
Outdated
Show resolved
Hide resolved
I'll have another go at the class loading stuff after the other two PRs are in. Can't handle all the parallelity in my brain. 🤣 |
I could get rid of the serializing deserializing, but I couldn't get rid of the The problem is the following:
I hope this helps to understand, why I did it in this way. If there is an easier or more elegant solution, I'm all for it. 😄 |
- SortPomCfg needs no dependencies, just Strings and booleans - SortPomCfg now has the default values, which simplifies plugin-maven/.../SortPom.java - SortPomStep does the JarState and classloader stuff
…ineClass`, and `com.diffplug.spotless` with `buildToolClassLoader`. This unifies FeatureClassLoader with DelegatingClassLoader.
…`SortPomFormatterFunc` needs `src/sortPom/java`.
Well I broke eclipse, but I fixed PomStep. Does this approach look good to you @tisoft? You got all the hard parts working, I just massaged things around with an eye towards other parts of Spotless adopting this same "glue" approach. |
* | ||
* For `com.diffplug.spotless.glue.`, classes are redefined from within the lib jar | ||
* but linked against the `Url[]`. This allows us to ship classfiles which function as glue | ||
* code but delay linking/definition to runtime after the user has specified which version | ||
* of the formatter they want. | ||
* | ||
* For `"org.slf4j.` and (`com.diffplug.spotless.` but not `com.diffplug.spotless.extra.`) | ||
* the classes are loaded from the buildToolClassLoader. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fvgh, just FYI, we finally have a way to ship glue code without requiring all deps of that glue code. It works like so:
com.diffplug.spotless.glue.
-> we define classes from the jars, which requires linking againstcom.diffplug.spotless
frombuildToolClassLoader
- we make an exception for
com.diffplug.spotless.extra
, which we always load from the jars as (we have in the past) - we also load
org.slf4j.
frombuildToolClassLoader
(as we have in the past)
This will allow us to replace a lot of manual reflection code, ala #524.
@nedtwigg Added documentation and changelog entries. |
Released in |
I advise the following:
I also anticipate that you will want to add a |
Adds the sorting mechanism of the sortpom-maven-plugin.
While the sortpom-maven-plugin is a maven plugin in itself, I like all my code formatting in one plugin, so this PR integrates the pom sorting from that plugin. Configuration options are the same as in the upstream project.