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

ErrorProneInjector incorrectly picks up the no-args constructor #3931

Closed
ksobolew opened this issue May 25, 2023 · 11 comments
Closed

ErrorProneInjector incorrectly picks up the no-args constructor #3931

ksobolew opened this issue May 25, 2023 · 11 comments

Comments

@ksobolew
Copy link

The logic of determining the constructor of a checker class changed in commit 1c3c09f. Previously it explicitly checked for a constructor with a single parameter of type ErrorProneFlags; now it looks for a constructor with all parameters having this type. The issue is that the condition used - allMatch - also returns true if there are no parameters at all, so the no-args constructor also matches the test.

The impact is that when I have a test for a checker which needs to take additional flags, the CompilationTestHelper uses the wrong constructor to create the checker instance, making it impossible to pass flags in a test.

@Stephan202
Copy link
Contributor

@ksobolew this sounds similar to something that initially puzzled me when upgrading to Error Prone 2.19+. Then I realized that just annotating the ErrorProneFlags-accepting constructors with @Inject suffices. See the changes in PicnicSupermarket/error-prone-support#621 for an example. Hope this helps!

@ksobolew
Copy link
Author

You're right @Stephan202, there's also some support for @Inject, so I think it will work for me too. But I still think this could be fixed, perhaps even with something like this:

diff --git a/check_api/src/main/java/com/google/errorprone/scanner/ErrorProneInjector.java b/check_api/src/main/java/com/google/errorprone/scanner/ErrorProneInjector.java
index 7a3c79cee5..afd2570d87 100644
--- a/check_api/src/main/java/com/google/errorprone/scanner/ErrorProneInjector.java
+++ b/check_api/src/main/java/com/google/errorprone/scanner/ErrorProneInjector.java
@@ -18,6 +18,7 @@ package com.google.errorprone.scanner;
 
 import static com.google.common.collect.Lists.reverse;
 import static java.util.Arrays.stream;
+import static java.util.Comparator.comparingInt;
 import static java.util.stream.Collectors.joining;
 
 import com.google.common.collect.ClassToInstanceMap;
@@ -106,7 +107,7 @@ public final class ErrorProneInjector {
     return stream(clazz.getDeclaredConstructors())
         .filter(predicate)
         .map(c -> (Constructor<T>) c)
-        .findFirst();
+        .max(comparingInt(Constructor::getParameterCount));
   }
 
   private static String printPath(List<Class<?>> path) {

@Stephan202
Copy link
Contributor

Check; I suppose that's something for @graememorgan to have an opinion on :)

@graememorgan
Copy link
Member

Hah, I think I thought of that edge case when I wrote it, but decided it wouldn't matter for some reason. :)

I would expect the inject constructor to be annotated @Inject and therefore win.

The impact is that when I have a test for a checker which needs to take additional flags, the CompilationTestHelper uses the wrong constructor to create the checker instance, making it impossible to pass flags in a test.

Could you provide a minimal example which is a problem?

@Stephan202
Copy link
Contributor

Stephan202 commented May 25, 2023

Could you provide a minimal example which is a problem?

IIRC ~any test that provides a non-vacuous set of flags using setArgs should trigger the issue.

One example:

git clone git@github.com:PicnicSupermarket/error-prone-support.git
cd error-prone-support
sed -i '/Inject/d' error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/RedundantStringConversion.java
mvn clean install -Dverification.skip -DskipTests
mvn test -Dtest='RedundantStringConversionTest#identificationOfCustomConversionMethod' -pl error-prone-contrib

@graememorgan
Copy link
Member

sed -i '/Inject/d' error-prone-contrib/src/main/java/tech/picnic/errorprone/bugpatterns/RedundantStringConversion.java

But can it be fixed by just including the @Inject? Ideally we'd like @Inject to be used for the injectable constructor.

(I'm not suggesting not fixing this to match the original behaviour, but chucking some @Injects around would be good anyway.)

@Stephan202
Copy link
Contributor

Indeed, at least in our project adding @Inject to these non-nullary constructors solved the issue in each case 👍

@ksobolew
Copy link
Author

Yes, it can be fixed this way. I originally didn't realize that, so the severity is much lower than I thought. Now it's just mostly a source of confusion :)

@Stephan202
Copy link
Contributor

The warning-level InjectOnBugCheckers check should help, though many may have disabled it due to the false-positives it reported in an earlier version. Perhaps adding a hint to the release notes could also help. :)

@graememorgan
Copy link
Member

I've mailed a change internally to favour an EPF constructor over a no-arg one.

copybara-service bot pushed a commit that referenced this issue May 26, 2023
I was a bit lazy and figured this edge case wouldn't matter too much, but it turns out to annoy people.

Fixes external #3931

PiperOrigin-RevId: 535251926
copybara-service bot pushed a commit that referenced this issue May 26, 2023
I was a bit lazy and figured this edge case wouldn't matter too much, but it turns out to annoy people.

Fixes external #3931

PiperOrigin-RevId: 535251926
copybara-service bot pushed a commit that referenced this issue May 26, 2023
I was a bit lazy and figured this edge case wouldn't matter too much, but it turns out to annoy people.

Fixes external #3931

PiperOrigin-RevId: 535569770
@graememorgan
Copy link
Member

Should be fixed now; give me a shout about any further problems.

benkard pushed a commit to benkard/jgvariant that referenced this issue Jun 18, 2023
This MR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [com.google.errorprone:error_prone_core](https://errorprone.info) ([source](https://github.com/google/error-prone)) |  | minor | `2.19.1` -> `2.20.0` |
| [com.google.errorprone:error_prone_annotations](https://errorprone.info) ([source](https://github.com/google/error-prone)) | compile | minor | `2.19.1` -> `2.20.0` |

---

### Release Notes

<details>
<summary>google/error-prone</summary>

### [`v2.20.0`](https://github.com/google/error-prone/releases/tag/v2.20.0): Error Prone 2.20.0

[Compare Source](google/error-prone@v2.19.1...v2.20.0)

Changes:

-   This release is compatible with early-access builds of JDK 21.

New Checkers:

-   [`InlineTrivialConstant`](https://errorprone.info/bugpattern/InlineTrivialConstant)
-   [`UnnecessaryStringBuilder`](https://errorprone.info/bugpattern/UnnecessaryStringBuilder)
-   [`BanClassLoader`](https://errorprone.info/bugpattern/BanClassLoader)
-   [`DereferenceWithNullBranch`](https://errorprone.info/bugpattern/DereferenceWithNullBranch)
-   [`DoNotUseRuleChain`](https://errorprone.info/bugpattern/DoNotUseRuleChain)
-   [`LockOnNonEnclosingClassLiteral`](https://errorprone.info/bugpattern/LockOnNonEnclosingClassLiteral)
-   [`MissingRefasterAnnotation`](https://errorprone.info/bugpattern/MissingRefasterAnnotation)
-   [`NamedLikeContextualKeyword`](https://errorprone.info/bugpattern/NamedLikeContextualKeyword)
-   [`NonApiType`](https://errorprone.info/bugpattern/NonApiType)

Fixes issues: [#&#8203;2232](google/error-prone#2232), [#&#8203;2243](google/error-prone#2243), [#&#8203;2997](google/error-prone#2997), [#&#8203;3301](google/error-prone#3301), [#&#8203;3843](google/error-prone#3843), [#&#8203;3903](google/error-prone#3903), [#&#8203;3918](google/error-prone#3918), [#&#8203;3923](google/error-prone#3923), [#&#8203;3931](google/error-prone#3931), [#&#8203;3945](google/error-prone#3945), [#&#8203;3946](google/error-prone#3946)

**Full Changelog**: google/error-prone@v2.19.1...v2.20.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever MR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNC4yNC4wIiwidXBkYXRlZEluVmVyIjoiMzQuMjQuMCJ9-->
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

No branches or pull requests

3 participants