-
-
Notifications
You must be signed in to change notification settings - Fork 9.2k
[JENKINS-68652] Update ANTLR2 to ANTLR4 #7293
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
Conversation
This updates the ANTLR2 grammars to ANTLR4 and updates the Jenkins code to handle changes in API for ANTLR4.
|
I also built Jenkins with Java 18 and there were no issues during build. |
|
The Launching Jenkins causes https://gist.githubusercontent.com/NotMyFault/0a4c3222354d31106ab2d41610709d7c/raw/d3e2506ab6dbd878ed89d67bcc56ee89e20bf779/gistfile1.txt |
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.
Thanks for stepping up to contribute to this effort! I pushed a few commits to sort out minor linting issues.
Lots of plugins import antlr.ANTLRException from Jenkins core, so you will have to come up with a strategy for backward compatibility. For example you could define a new class in core/src/main/java/antlr/ANTLRException.java that either extends org.antlr.v4.runtime.misc.ParseCancellationException or org.antlr.v4.runtime.RecognitionException or stands on its own in the type hierarchy with utility methods to convert the ANTLR 4 exception classes to and from instances of core/src/main/java/antlr/ANTLRException.java. Make sure to test that plugins compiled against older Jenkins cores continue to work with these changes and that plugins compiled against these changes don't require source modifications.
|
The code search link doesn't show me anything, is there something I need to setup in GitHub? |
|
You're probably just not part of the GitHub Code Search beta program. https://github.com/search?ref=simplesearch&type=Code&q=user%3Ajenkinsci+%22import+antlr%22 should work as long as you are logged into GitHub. You can ignore the results in |
|
Also consider linting the ANTLR4 files by adding diff --git a/pom.xml b/pom.xml
index b1ef08a9b0..840a7c449d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -391,6 +391,9 @@ THE SOFTWARE.
<artifactId>spotless-maven-plugin</artifactId>
<version>${spotless.version}</version>
<configuration>
+ <antlr4>
+ <antlr4Formatter />
+ </antlr4>
<java>
<endWithNewline />
<importOrder />and checking in the result of |
This is just a concrete example of the general compatibility problem I described above. The first error there is showing how this PR breaks compatibility with |
|
Yes, I obviously don't want to break compatibility. I will work on that later today. |
|
Some tips from someone who has done this a few times: think about not only how to cross over into the new world but the long term desired end goal. From the consumers I looked at, a lot of them don't seem like they really care about |
| public static Label parseExpression(@NonNull String labelExpression) throws ANTLRException { | ||
| LabelExpressionLexer lexer = new LabelExpressionLexer(new StringReader(labelExpression)); | ||
| return new LabelExpressionParser(lexer).expr(); | ||
| public static Label parseExpression(@NonNull String labelExpression) throws ParseCancellationException { |
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.
Effective Java 3rd Edition §74 says:
Use the Javadoc
@throwstag to document each exception that a method can throw, but do not use thethrowskeyword on unchecked exceptions.
Here and elsewhere, any instances of throws ParseCancellationException should be deleted in favor of a Javadoc @throws tag.
Also consider loosening the contract in the @throws tag to specify something further up in ParseCancellationException's type hierarchy, such as CancellationException or IllegalStateException (and updating the @deprecated message in ANTLRException accordingly). The advantage in declaring the contract in terms of pure Java Platform types is that it prevents callers from relying on a type that is subject to change in the future. In other words, this would be a smart move that would make life easier for whoever is upgrading us from ANTLR4 to the next big thing. By defining our API in terms of pure Java types, we are free to throw a specific subtype in the implementation (like org.antlr.v4.runtime.misc.ParseCancellationException) but also leave ourselves the option of throwing some other type in the future (as long as it inherits from the Java Platform type we specify in the contract) rather than tying ourselves to the specific ANTLR4 implementation.
| lexer.addErrorListener(new ANTLRErrorListener() { | ||
| @Override | ||
| public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { | ||
| throw new ParseCancellationException(msg); |
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.
Here and elsewhere, we need to throw our new subtype of ParseCancellationException (ANTLRException) in order to provide actual compatibility (not just linker pacification) for callers like https://github.com/jenkinsci/periodicbackup-plugin/blob/92b9ebaa0758333256e3478ea8cff5bc07b28085/src/main/java/org/jenkinsci/plugins/periodicbackup/PeriodicBackup.java#L76-L78 that are expecting an ANTLRException to be thrown in order to catch it and do something interesting. Although we expect those callers to eventually migrate to catching ParseCancellationException instead (due to the @deprecation Javadoc I added in commit c63d928), existing callers that were compiled against older cores still need to get the same behavior they are already expecting. It is only after we have made a good faith effort to migrate callers from ANTLRException to ParseCancellationException (and released those PRs!) that we can consider changing core's behavior to throw something that is not assignable to ANTLRException.
|
Thanks @basil I will get to this feedback as soon as I can. I am not a full on Java guy, so feedback for these type of things is very much appreciated. |
basil
left a comment
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 pushed some commits to complete this work:
- Use
antlr4-runtimerather thanantlr4to avoid unnecessary JARs in the WAR - Remove ANTLR4 exception types from API contracts in favor of
IllegalArgumentException - Configure both lexers/parsers consistently (no default error listener, consistent custom error listener, no
BailErrorStrategy) - Throw
InputMismatchExceptioninBaseParserfor consistency with superclass - Test compatibility path in unit tests
- Extract ANTLR version to Maven property for easier updating
- Remove unnecessary executions from top-level pom.xml
- Bonus: Add stack trace detail message to
TimerTrigger#doCheckSpec
Testing done:
- Verified interactively in the GUI by validating label expressions and cron strings, both correct and incorrect, and confirming the expected error messages were displayed with appropriate line and column numbers
- Verified that
cloudbees-folderas well as a custom plugin that both threw and caughtANTLRException, worked fine when compiled against 2.375 but executed against this PR - Verified that
cloudbees-folderas well as a custom plugin that both threw and caughtANTLRExceptioncompiled with no errors against the core from this PR - Verified that
cloudbees-folderas well as a custom plugin that defined a custom trigger did not compile against 2.375 after references toANTLRExceptionwere removed but did compile against this PR - Verified that the WAR file did not include any new unexpected JARs
- Verified that no unexpected log messages were printed to the Jenkins log
NotMyFault
left a comment
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.
Thanks for taking care of this task, @slide! This is an important step forward, not only the migration from a 15+ year old dependency, this upgrade allows compiling Jenkins with Java versions newer than 17 also 🎉
|
This PR is now ready for merge. We will merge it after approximately 24 hours if there is no negative feedback. Please see the merge process documentation for more information about the merge process. Thanks! |
|
Thanks for the feedback for getting this merged. |
This is no longer being thrown by Crontab constructor jenkinsci/jenkins#7293

See JENKINS-68652.
Testing done
Ran the LabelExpressionTest and Cron*Tests
Proposed changelog entries
Proposed upgrade guidelines
N/A
Submitter checklist
@Restrictedor have@since TODOJavadocs, as appropriate.@Deprecated(since = "TODO")or@Deprecated(forRemoval = true, since = "TODO"), if applicable.evalto ease future introduction of Content Security Policy (CSP) directives (see documentation).Desired reviewers
@basil @oleg-nenashev
Maintainer checklist
Before the changes are marked as
ready-for-merge:upgrade-guide-neededlabel is set and there is a Proposed upgrade guidelines section in the pull request title (see example).lts-candidateto be considered (see query).