Skip to content
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

Add Checkstyle plugin #3472

Closed
wants to merge 31 commits into from
Closed

Add Checkstyle plugin #3472

wants to merge 31 commits into from

Conversation

m50d
Copy link

@m50d m50d commented Sep 6, 2024

(Commits not clean as I'm expecting to squash)

Fix: #3332

@m50d
Copy link
Author

m50d commented Sep 6, 2024

Build failures look like test infra flakiness/races (not finding the just-published module for the integration test, and a concurrent file opening error on Windows) rather than real issues?

@lihaoyi
Copy link
Member

lihaoyi commented Sep 7, 2024

Will take a look. Our test suite is flaky, I've been working on it but not 100% stabilized yet

@lihaoyi
Copy link
Member

lihaoyi commented Sep 7, 2024

Manually retries those jobs

*
* @author Andrew Johnson
*/
case class CheckstyleXSLTSettings(xslt: File, output: File)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually need an output: File for each XSLT transformation? If we're always applying the same transformations in the same sequence on the input checkstyle config between using it, the choice of output file name seems irrelevant and seems like something Mill can manage

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the idea is that each transformation has its own output file (e.g. one transformation for a human-readable HTML page and one for some kind of internal XML report). To be honest it's not a feature I've used, just trying to retain parity with the SBT plugin.

}

/** An optional set of XSLT transformations to be applied to the checkstyle output */
def checkstyleXsltTransformations: T[Option[Set[CheckstyleXSLTSettings]]] = T.input { None }
Copy link
Member

@lihaoyi lihaoyi Sep 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type signature here looks a bit off. Do we need it to be wrapped in Option, when it could be a Set.empty? If transforms are to be run sequentially, and the ordering matters, should it be a Seq instead? Should we provide a default path to put the file, or default folder to scan for such files, like how we look for T.workspace / "checkstyle-config.xml" above?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that there's no point in the Option wrapping, will fix that.

I think this is a pretty niche feature so probably the default should be no such file.

Comment on lines +13 to +15
sealed trait CheckstyleConfigLocation {
def read(resources: Seq[Path]): String
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this trait hierarchy be simplified? Classpath seems strange, since it's loading stuff from the Mill classloader, which won't contain any of the application classpath.

URL seems redundant, since if we ask for a file, Mill can convert that into a URL by doing override def foo = T{ requests.get("...") }, so I don't think we need to have a special case for it in the configuration ADT.

Given that, it might be best to just make the config a PathRef, and led anyone who wants to fetch that file from unusual locations just do an override the task to call requests.get or os.read(os.resource / ...) themselves

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Classpath uses the application's dependencies (if you comment out the dependency in the checkstyleClasspathConfig test it will fail). I think that's an important use case (use a config that's published in some organisational jar). Happy to cut URL if you still think that's worthwhile given that we do need the ADT?

import mill.{Agg, T}
import mill.scalalib.{Dep, DepSyntax, JavaModule}
import mill.util.Jvm
import net.sf.saxon.s9api.Processor
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious why we need this external dependency for Processor? What is it doing that we cannot do via scala.xml or javax.xml?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just took the impl from the SBT plugin, I don't have a particular preference myself.

Comment on lines 15 to 20
> ./mill checkstyle # Run checkstyle to produce a report, optionally failing the build if violations are severe enough
Checkstyle warning found in ...src/InputFileName1.java:2: Top-level class MyAnnotation1 has to reside in its own source file.
Checkstyle warning found in ...src/InputFileName1.java:13: Top-level class Enum1 has to reside in its own source file.
Checkstyle warning found in ...src/InputFileName1.java:26: Top-level class TestRequireThisEnum has to reside in its own source file.
3 issue(s) found in Checkstyle report: ...out/checkstyle.dest/checkstyle-report.xml
error: ...Checkstyle issues found
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's flesh this out a bit more:

  • Assert on a handful of different checkstyle errors, not just Top-level class has to reside in its own source file
  • Let's exercise the process of fixing the errors: we can run sed to mangle the files (see other example tests), and run checkstyle again and verify that it no longer errors

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with fixing and checking it passes, have extended the test to cover that part.

What sort of different errors do we want to cover? I don't see a lot of value in duplicating the whole checkstyle checksuite, we're not really exercising the plugin code more by having more than a couple of errors (as long as we can pick up more than 1 error reported by checkstyle, I can't see any reasonable way for the plugin to break on a different error), but happy to add any you think are important.

@m50d m50d requested a review from lihaoyi September 9, 2024 07:41
@lihaoyi
Copy link
Member

lihaoyi commented Sep 12, 2024

@m50d I'm going to go with #3516 as the implementation, but I'll pay out 30% of the bounty for the effort you put into this. Email me your bank transfer detail and I'll wire it over. Thanks for working through this with me, and this code has definitely been useful in helping me understand the solution and design space even though we may not end up merging it

@lihaoyi lihaoyi closed this Sep 12, 2024
lihaoyi added a commit that referenced this pull request Sep 12, 2024
* Set `check = true` and `stdout = true` by default since that's what
I'm guessing people will expect
* Extract out `def checkstyleHandleErrors` and `def checkstyle0` for
re-use between `CheckstyleModule` and `CheckstyleXsltModule`. This
allows `def checkstyle` to throw errors and report to console while
still generating the XSLT reports in `CheckstyleXsltModule`
* Avoid reporting `no violations` when exit code is zero, because there
may still be warnings
* Integrate the example test from @m50d's checkstyle PR
#3472, flesh it out, and
integrate it into the docsite
@m50d
Copy link
Author

m50d commented Sep 27, 2024

Thank you - glad to have contributed something and agreed that that's ultimately the better approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Java Checkstyle Plugin (1000USD Bounty)
2 participants