GeezerVison is showing github.com — Added support for Maven POM sorting/formatting by tisoft · Pull Request #946 · diffplug/spotless
Conversation
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.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Documentation is still missing, would like to know if this is something you want inside spotless, before I do the tedious documentation work. 😄
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
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.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
|
// 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); |
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Comment on lines
+98
to
+132
|
|
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
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
@nedtwigg I played around with #524. Classloading is a bit awkward... Do you have any better idea?
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
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())); |
https://github.com/diffplug/spotless/blob/main/lib/src/main/java/com/diffplug/spotless/FeatureClassLoader.java
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 inside JarState
- 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!
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
|
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. 🤣
|
nedtwigg reacted with laugh emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
I could get rid of the serializing deserializing, but I couldn't get rid of the DelegatingClassLoader.
The problem is the following:
- The
SortPomFormatterFunc directly references classes from the sortpom dependency
- so we can't load it from the current
ClassLoader, since that doesn't know about the sortpom dependencies
- we can't load it from the
JarState ClassLoader, since that doesn't know about SortPomFormatterFunc, SortPomState and FormatterFunc
- So we need a
ClassLoader, that knows about both
- My first idea was to change the
FeatureClassLoader to allow loading SortPomFormatterFunc from the buildToolClassLoader
- This would attach
SortPomFormatterFunc to the buildToolClassLoader
- As soon as the constructor is retrieved via reflection, the dependencies of the class will be tried to load with the
buildToolClassLoader
- This fails, since the
buildToolClassLoader doesn't know about the sortpom package, since it is effectively a parent from the `FeatureClassLoader, and classes from it's children are invisible
- So the
SortPomFormatterFunc needs to be attached to a ClassLoader, that knows about the sortpom package: the DelegatingClassLoader
- It uses the current
ClassLoader and the FeatureClassLoader as sources
- But it doesn't load the classes directly from them (since they would be attached to the source classloaders, bringing us back to the previous problem)
- Instead it loads the classes as resources, and then calls define class, to attach them to the
DelegatingClassLoader
- Now
SortPomFormatterFunc and all classes from the 'JarState' are loaded by the same Classloader and can see each other and all is fine...
- ... except that now
SortPomState and FormatterFunc are also attached to DelegatingClassLoader and the funny De-/Serializing of the state and the call to 'apply' via reflection is needed
- That's why the
DelegatingClassLoader now excludes those 2 classes from the custom classloading process and just returns the Class objects already loaded
- Which only works, if the
SortPomState and its member fields are public
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. 😄
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
- 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.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Comment on lines
+34
to
+41
|
|
*
|
|
|
* 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.
|
nedtwigg
Sep 30, 2021
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
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 against com.diffplug.spotless from buildToolClassLoader
- 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. from buildToolClassLoader (as we have in the past)
This will allow us to replace a lot of manual reflection code, ala #524.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
@tisoft I think all we need now are changelog updates and documentation. Another fantastic PR, thanks very much! You were the savior to come and finally figure out how we can do #524, which will make the project much easier to read and contribute to.
|
tisoft reacted with thumbs up emoji
jbduncan reacted with hooray emoji
All reactions
-
👍
1 reaction
-
🎉
1 reaction
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
@nedtwigg Added documentation and changelog entries.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Released in plugin-maven 2.15.0
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
I advise the following:
- test in a production setting to make sure that the published artifact has the glue code
- once it is confirmed working, submit a PR to https://github.com/Ekryd/sortpom showing how to use it with spotless
I also anticipate that you will want to add a version property to SortPomCfg, so that you can use the latest version of sortpom without needing to publish a whole new set of Spotless artifacts each time, but that can wait until it's needed.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|