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

Parameter name lost during Gradle's incremental compilation #5236

Closed
4 tasks done
martijndwars opened this issue Apr 12, 2021 · 8 comments
Closed
4 tasks done

Parameter name lost during Gradle's incremental compilation #5236

martijndwars opened this issue Apr 12, 2021 · 8 comments
Assignees
Labels
type: bug Something isn't working
Milestone

Comments

@martijndwars
Copy link
Contributor

martijndwars commented Apr 12, 2021

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

  1. git clone https://github.com/MartijnDwars/mn-test
  2. cd mn-test
  3. ./gradlew compileJava
  4. Update in src/main/java/mn/test/ByeController.java the text "Bye $n" to "Byte $n+1".
  5. ./gradlew compileJava

The first compileJava runs fine, but the second compileJava fails with the following error:

> Task :compileJava FAILED
error: The route declares a uri variable named [id], but no corresponding method argument is present
Note: Creating bean classes for 2 type elements
1 error

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler error output for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s
1 actionable task: 1 executed

For what it's worth, if you run compileJava a third time it would succeed. Also, if you run clean compileJava you do not run into this problem, so this seems specific to some incremental compilation. I stumbled upon this issue when building through IntelliJ, which internally delegates to Gradle's compileJava.

Expected Behaviour

Both compileJava tasks should succeed.

Actual Behaviour

The second compileJava fails with the following error: The route declares a uri variable named [id], but no corresponding method argument is present. I believe the following is happening:

  1. I change ByeController.java, so incremental compilation triggers only the recompilation of ByeController.java.
  2. The Java compiler loads the already-compiled HelloController.class file.
  3. The Java compiler ignores parameter names in this class file, even though the parameter names are present.
  4. The annotation processor runs on HelloController (even though this class is already compiled and not changed).
  5. The MissingParameterRule is unable to match the arg0 parameter to the route and produces an error.

Environment Information

  • Operating System: macOS 10.15.7
  • Micronaut Version: Using io.micronaut.application Gradle plugin version 1.4.2 (Micronaut 2.4.2).
  • JDK Version: 1.8.0_281

Example Application

See https://github.com/martijndwars/mn-test

@martijndwars
Copy link
Contributor Author

martijndwars commented Apr 12, 2021

Perhaps this ticket should be moved to https://github.com/micronaut-projects/micronaut-gradle-plugin/? If someone could confirm that this is indeed a bug, then I would be happy to contribute a fix.

@graemerocher
Copy link
Contributor

Seems to be a bug in Java 8, works with JDK 11

@martijndwars
Copy link
Contributor Author

martijndwars commented Apr 13, 2021

Thanks for checking Graeme! I'm not sure what the guarantees for incremental annotation processing are, so this could be a bug in Java 8 or it could be Micronaut depending on unspecified behavior. Either way, does it make sense for Micronaut to run parameter validation on classes which are already compiled? E.g. if I incrementally compile only B.java, then should Micronaut validate the already-compiled A.class? If not, then perhaps this bug could be solved by simply not running validation on already-compiled classes?

@graemerocher
Copy link
Contributor

I'm not sure it is possible to know from the perspective of an annotation processor whether an element is compiled or not. I suspect what is happening is that Java is loading a TypeElement from the compiled class and this is not representing named parameters correctly. I think given this behaviour we should disable this validation if incremental=true and Java version is 8

@graemerocher
Copy link
Contributor

graemerocher commented Apr 13, 2021

that could be configured here

String prop = visitorContext.getOptions().getOrDefault(VALIDATION_OPTION, "true");

@graemerocher graemerocher added the type: bug Something isn't working label Apr 14, 2021
@graemerocher graemerocher self-assigned this Apr 14, 2021
@graemerocher graemerocher added this to the 2.4.3 milestone Apr 14, 2021
@martijndwars
Copy link
Contributor Author

@graemerocher I tried to create a fix in 5850bf9. Is it worth opening a PR, or are you working on a change yourself already?

@graemerocher
Copy link
Contributor

graemerocher commented Apr 14, 2021

I haven't started yet, so go ahead an open a PR. The change looks good.

@graemerocher
Copy link
Contributor

Thanks for the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants