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

By default, prevent BugCheckers from introducing new dependencies #308

Merged
merged 6 commits into from
Oct 29, 2022

Conversation

Stephan202
Copy link
Member

@Stephan202 Stephan202 commented Oct 23, 2022

As-is, this is especially relevant for users who do not use Guava or the New Relic Agent API, as mentioned here. Note that most BugCheckers don't need to be modified, since any third-party references in their suggestions must already be present if the check is to trigger at all.

Suggested commit message:

By default, prevent `BugChecker`s from introducing new dependencies (#308)

We should implement something similar for Refaster, but that will look quite different (and is out of scope for this PR).

@Stephan202 Stephan202 added this to the 0.5.0 milestone Oct 23, 2022
@Stephan202 Stephan202 requested a review from rickie October 23, 2022 17:35
@rickie rickie mentioned this pull request Oct 25, 2022
2 tasks
@rickie rickie linked an issue Oct 25, 2022 that may be closed by this pull request
2 tasks
Copy link
Member

@rickie rickie left a comment

Choose a reason for hiding this comment

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

Added a commit.

First round of review 👀:smile:.

* the given context.
*
* @param state The context under consideration.
* @return {@code true} iff if it is okay to assume or create a dependency on this library.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* @return {@code true} iff if it is okay to assume or create a dependency on this library.
* @return {@code true} iff it is okay to assume or create a dependency on this library.

@@ -48,7 +49,8 @@ public final class ScheduledTransactionTrace extends BugChecker implements Metho

@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
if (!IS_SCHEDULED.matches(tree, state)) {
if (!ThirdPartyLibrary.NEW_RELIC_AGENT_API.canUse(state)
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 want to add ThirdPartyLibary to StaticImport#STATIC_IMPORT_EXEMPTED_MEMBERS?

Copy link
Member Author

Choose a reason for hiding this comment

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

No strong opinion. 😄

Copy link
Member Author

Choose a reason for hiding this comment

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

I see a +1, so will do.

Copy link
Member Author

@Stephan202 Stephan202 left a comment

Choose a reason for hiding this comment

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

Tnx for the typo fixes :)

@@ -48,7 +49,8 @@ public final class ScheduledTransactionTrace extends BugChecker implements Metho

@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
if (!IS_SCHEDULED.matches(tree, state)) {
if (!ThirdPartyLibrary.NEW_RELIC_AGENT_API.canUse(state)
Copy link
Member Author

Choose a reason for hiding this comment

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

No strong opinion. 😄

* @param state The context under consideration.
* @return {@code true} iff it is okay to assume or create a dependency on this library.
*/
public boolean canUse(VisitorState state) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Note to self: ponder a better name. I didn't select isSupported because it doesn't seem to jive with IGNORE_CLASSPATH_COMPAT_FLAG, but perhaps we should use that name anyway. Or perhaps something else?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think canUse is fine, especially if we plan to add more fine-grained control.
In this case I think canUse makes more sense than isSupported (or isAvailable) as the library might be available on the classpath, but like the XXX mentions new usages could be undesirable.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I was also thinking about this.

isAllowedToUse (is allowed might a bit more "accurate" as shouldIgnoreClasspath is part of that check, although it is very similar to canUse)?

Copy link
Member Author

Choose a reason for hiding this comment

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

I like "allowed". How about isIntroductionAllowed? (Will push, but feel free to challenge.)

Copy link
Member

Choose a reason for hiding this comment

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

Read the Javadocs and goal of the class again.

Have three other options: isUsageAllowed, isReferencingAllowed, isReferenceAllowed.

To me, the ThirdPartyLibrary#isIntroductionAllowed sounds a bit like the question: Is it okay if we introduce this third party library (at all)? The name of the method does not 100% match with the Javadoc of the class, as it mentions "introducing references". So I'd say that isReferencingAllowed could make the whole intent of the class even clearer (and is for that reason the one I like most). WDYT?

Copy link
Member

@rickie rickie Oct 26, 2022

Choose a reason for hiding this comment

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

We discussed this offline for a while.

@Stephan202 explained his reasoning behind isIntroductionAllowed. I see where you are coming from and it is a good reasoning. He gave the example that one might use Guava but wishes to migrate away from it and therefore using / introducing new usages is not allowed. I'm fine with following the proposed change but, to be honest, I'm not 100% convinced yet and feel isUsingAllowed or isIntroducingUsageAllowed would be the clearest option 🤔. Don't have additional arguments besides the ones already mentioned, sorry.

@oxkitsune oxkitsune self-requested a review October 26, 2022 07:28
Copy link
Contributor

@oxkitsune oxkitsune left a comment

Choose a reason for hiding this comment

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

Cool stuff! Left some questions and opinions 😄

Would be interesting to see whether we could make a bug checker that enforces ThirdPartyLibrary usage in bug checkers 🤯

.errorProneOptions()
.getFlags()
.getBoolean(IGNORE_CLASSPATH_COMPAT_FLAG)
.orElse(Boolean.FALSE);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
.orElse(Boolean.FALSE);
.orElse(false);

What's the reason for using Boolean.FALSE over just false 🤔

Copy link
Member

Choose a reason for hiding this comment

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

Because the getBoolean expects a Boolean and otherwise there would be an implicit cast from the boxed false variant.

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>provided</scope>
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
<scope>provided</scope>
<scope>test</scope>

Considering org.springframework.scheduling.annotation.Scheduled is only explicitly used in ScheduledTransactionTraceTest shouldn't using <scope>test</scope> be enough?

Copy link
Member

@rickie rickie left a comment

Choose a reason for hiding this comment

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

Some final notes, PR looks nice!

@SuppressWarnings("ImmutableEnumChecker" /* Supplier is deterministic. */)
private final Supplier<Boolean> canUse;

ThirdPartyLibrary(String witnessFqcn) {
Copy link
Member

Choose a reason for hiding this comment

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

IMO it would be nice to add some Javadoc here. I understand what witnessFqcn is in this context, but might be nice to add some explanation here as well.

* @param state The context under consideration.
* @return {@code true} iff it is okay to assume or create a dependency on this library.
*/
public boolean canUse(VisitorState state) {
Copy link
Member

Choose a reason for hiding this comment

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

Yeah I was also thinking about this.

isAllowedToUse (is allowed might a bit more "accurate" as shouldIgnoreClasspath is part of that check, although it is very similar to canUse)?

.errorProneOptions()
.getFlags()
.getBoolean(IGNORE_CLASSPATH_COMPAT_FLAG)
.orElse(Boolean.FALSE);
Copy link
Member

Choose a reason for hiding this comment

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

Because the getBoolean expects a Boolean and otherwise there would be an implicit cast from the boxed false variant.

@Stephan202
Copy link
Member Author

Thanks for the review and fix @oxkitsune and @rickie! I'll circle back to this PR ~later today (many meetings; let's see :D).

@Stephan202 Stephan202 force-pushed the sschroevers/better-classpath-awareness branch from f64bf4d to 13c862b Compare October 26, 2022 10:13
Copy link
Member Author

@Stephan202 Stephan202 left a comment

Choose a reason for hiding this comment

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

Rebased and added a commit. We could also move the StaticImport changes and investigation to a separate PR. (If we do want to keep it here, then eventually the suggested commit message should be updated, too.)

* @param state The context under consideration.
* @return {@code true} iff it is okay to assume or create a dependency on this library.
*/
public boolean canUse(VisitorState state) {
Copy link
Member Author

Choose a reason for hiding this comment

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

I like "allowed". How about isIntroductionAllowed? (Will push, but feel free to challenge.)

@@ -48,7 +49,8 @@ public final class ScheduledTransactionTrace extends BugChecker implements Metho

@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
if (!IS_SCHEDULED.matches(tree, state)) {
if (!ThirdPartyLibrary.NEW_RELIC_AGENT_API.canUse(state)
Copy link
Member Author

Choose a reason for hiding this comment

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

I see a +1, so will do.

@@ -102,7 +102,8 @@ public final class StaticImport extends BugChecker implements MemberSelectTreeMa
"org.springframework.http.MediaType",
"org.testng.Assert",
"reactor.function.TupleUtils",
"tech.picnic.errorprone.bugpatterns.util.MoreTypes");
"tech.picnic.errorprone.bugpatterns.util.MoreTypes",
"tech.picnic.errorprone.bugpatterns.util.ThirdPartyLibrary");
Copy link
Member Author

Choose a reason for hiding this comment

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

This doesn't cause the enum values to be statically imported. Need to investigate before merging this PR.

@@ -189,7 +190,8 @@ public final class StaticImport extends BugChecker implements MemberSelectTreeMa
"INSTANCE",
"newBuilder",
"of",
"valueOf");
"valueOf",
"values");
Copy link
Member Author

Choose a reason for hiding this comment

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

... but ThirdPartyLibrary.values(), would be statically imported, which is not something we want.

Copy link
Member Author

Choose a reason for hiding this comment

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

This should also be reverted.

@rickie
Copy link
Member

rickie commented Oct 26, 2022

Note that I mention in this comment that I want to add it to the STATIC_IMPORT_EXEMPTED_MEMBERS because I don't like statically importing this one. Primarily as it would mean loosing some context.

... but ThirdPartyLibrary.values(), would be statically imported, which is not something we want.

This is not true right? It would be prevented in the isCandidate method because it sees that values is in STATIC_IMPORT_EXEMPTED_IDENTIFIERS.

So I want to propose that I add a commit to move it. Which means that we defer looking into the issue with not importing 🤔. WDYT?

@rickie
Copy link
Member

rickie commented Oct 26, 2022

I see that we currently only allow to exempt specific members using STATIC_IMPORT_EXEMPTED_MEMBERS, which we could do as there are only 4 types in the enum. Nevertheless, let's defer it all together and investigate the issue + introduce support for easily adding a class to disallow all members thereof.

@Stephan202 Stephan202 force-pushed the sschroevers/better-classpath-awareness branch from b8fd499 to fec8d52 Compare October 29, 2022 11:29
Copy link
Member Author

@Stephan202 Stephan202 left a comment

Choose a reason for hiding this comment

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

Rebased and added a commit. As discussed offline: will merge once built.

Note that I mention in this comment that I want to add it to the STATIC_IMPORT_EXEMPTED_MEMBERS because I don't like statically importing this one. Primarily as it would mean loosing some context.

Okay, I misread that (but find it rather surprising; I don't see any issue with statically importing these, as long as it'd be done consistently 🤷).

... but ThirdPartyLibrary.values(), would be statically imported, which is not something we want.

This is not true right? It would be prevented in the isCandidate method because it sees that values is in STATIC_IMPORT_EXEMPTED_IDENTIFIERS.

Yes, because I added values in the context of this PR after making this observation...

@@ -189,7 +190,8 @@ public final class StaticImport extends BugChecker implements MemberSelectTreeMa
"INSTANCE",
"newBuilder",
"of",
"valueOf");
"valueOf",
"values");
Copy link
Member Author

Choose a reason for hiding this comment

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

This should also be reverted.

@Stephan202 Stephan202 merged commit 8fa3ff3 into master Oct 29, 2022
@Stephan202 Stephan202 deleted the sschroevers/better-classpath-awareness branch October 29, 2022 11:42
@rickie
Copy link
Member

rickie commented Oct 29, 2022

I don't see any issue with statically importing these

I think it is a bit less clear 🤷🏻.

Yes, because I added values in the context of this PR after making this observation...

Ahh I missed that change 😂, that's why I didn't revert it haha. Thanks for fixing that 😉.

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

Successfully merging this pull request may close these issues.

False positive against Sentry-Trace
3 participants