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

Treat impacted parameters from downstream dependencies as triggered fixes. #65

Merged
merged 42 commits into from
Sep 7, 2022

Conversation

nimakarimipour
Copy link
Member

@nimakarimipour nimakarimipour commented Sep 6, 2022

Resolves #64 by treating impacted parameters by downstream dependencies as triggered fixes while processing public methods.

It resolves the issue with race condition in unit tests as they are using a shared library model loader. This is resolved in the unit test infrastructure within this PR.

It also resolves issue with updating the stored impacts in downstream dependencies after each injection to prevent double counting.

It also contains huge refactoring over creation of Explorers.

@nimakarimipour nimakarimipour added the enhancement New feature or request label Sep 6, 2022
@nimakarimipour nimakarimipour self-assigned this Sep 6, 2022
@nimakarimipour nimakarimipour linked an issue Sep 6, 2022 that may be closed by this pull request
@nimakarimipour nimakarimipour changed the title [WIP] Treat impacted parameters from downstream dependencies as triggered fixes. Treat impacted parameters from downstream dependencies as triggered fixes. Sep 7, 2022
@nimakarimipour
Copy link
Member Author

@lazaroclapp This PR is ready for review. This changes made a lot of issues to avoid double counting since we are treating impacted parameters as triggered fixes. It also includes a refactoring to clean instantiating explorers since downstream dependency analysis is added as part of the explorers. Please let me know if you prefer to break this PR into multiple PRs. Thank you very much :)

@lazaroclapp
Copy link
Collaborator

Taking a look... not sure if I'll be able to finish my pass tonight, but for now, one thing worth pointing out is that the description for this PR seems incomplete, at the very least this is also solving the separate issue of the shared library models directory... (I think that would be an argument for it to be split into multiple PRs, each addressing a different bug or feature, but I also think we are short on time, so let me take a look as is, just make sure we document what this PR is actually changing 🙂 )

Copy link
Collaborator

@lazaroclapp lazaroclapp left a comment

Choose a reason for hiding this comment

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

Finishing this pass fairly late, hopefully I didn't misunderstand anything major, but here are a few comments 🙂 (If something is cryptic or unparsable, I can take a look and write a better comment tomorrow 😅 )

.collect(ImmutableSet.toImmutableSet());
}

/**
* Checks if the passed method, is declared in the target module.
* Checks if the passed location, is targeting an element declared in the target module.
Copy link
Collaborator

Choose a reason for hiding this comment

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

No comma needed here, I think.

Copy link
Member Author

@nimakarimipour nimakarimipour Sep 7, 2022

Choose a reason for hiding this comment

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

Removed it.

*/
public boolean declaredInModule(OnMethod location) {
return findNode(location.method, location.clazz) != null;
public boolean declaredInModule(@Nullable Location location) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

So, the only added caller of this method I see is methodDeclarationTree.declaredInModule(error.nonnullTarget.toMethod())) in DownstreamImpactAnalyzer. So, why change this from OnMethod to a generic Location and look only at the class? What am I missing?

Copy link
Member Author

Choose a reason for hiding this comment

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

To check if a location is defined in a module, we only need to check its enclosing class which this field, is shared among all Location subtypes. I thought there is no need to downcast to OnMethod and we can reuse this method for future changes. I removed the toMethod() which is not required anymore. 37018d0

@@ -59,7 +59,7 @@ public class Node {
public Set<Fix> triggeredFixes;

/** Collection of triggered errors if tree is applied. */
public ImmutableSet<Error> triggeredErrors;
public ImmutableList<Error> triggeredErrors;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why are we switching this to be a list, do we expect repetition?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, we can have multiple errors with same message nonNullTarget and type.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Um, can you give me an example here of distinct errors with the same messageType, message, and nonnullTarget that we want to keep track of? Also, any reason we can't simply refine what hashCode() takes into account so that distinct errors mean distinct elements in this list/set?

I still don't understand what changes when we change how we track parameter fixes coming from downstream deps that makes us now want to consider repetitions but not before (if this is a separate bug fix from the core change of this PR, then it being mixed together with this feature makes it harder to understand).

Copy link
Collaborator

Choose a reason for hiding this comment

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

Discussed offline, we probably want to track an issue here to switch back to a set once we have enough position info in errors.tsv to accurately distinguish separate errors in the same region with the same messageType and nonnullTarget, but for now this is not blocking 🙂

Copy link
Member Author

Choose a reason for hiding this comment

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

Please find the issue here #67.

import java.util.stream.Collectors;

/** Explorer for analyzing downstream dependencies. */
public class DownstreamImpactAnalyzer extends OptimizedExplorer {
Copy link
Collaborator

Choose a reason for hiding this comment

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

So, every other [Foo]Analyzer is part of the hierarchy rooted at GlobalAnalyzer, and every other subclass of Explorer is both named [Foo]Explorer and in the package explorers... why is this DownstreamImpactAnalyzer rather than DownstreamImpactExplorer?

Copy link
Collaborator

Choose a reason for hiding this comment

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

If this is meant to be used only through GlobalAnalyzerImpl and the idea here is to separate it from the "top level" explorers that can be used as the main driver of the analysis of "target", then maybe an option is:

  1. Clearly document this distinction in the javadoc for this class
  2. Still name it DownstreamImpactExplorer (or maybe: DownstreamImpactHelperExplorer)
  3. But leave it inside edu.ucr.cs.riple.core.global and make it package private.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, that is the idea. Applied your comments. Thank you :)
2634001

* on the target on downstream dependencies.
*
* @param tree Tree of the fix tree associated to root.
* @return Lower bound of number of errors on downstream dependencies.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should read "Upper bound of [...]"

Copy link
Member Author

Choose a reason for hiding this comment

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

Thank you for noticing this, fixed it. 7b8124d

this.tree = tree;
this.methods =
Multimaps.index(
tree.getPublicMethodsWithNonPrimitivesReturn().stream()
Copy link
Collaborator

Choose a reason for hiding this comment

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

So, just to be clear here, we still don't check for protected methods so we wouldn't see new errors caused by marking a protected method @Nullable and it being called within a subclass, right? (Not that we need that as part of this PR, just want to make sure we are tracking that limitation)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, we are not tracking that now, would you like me to create a follow up PR and add this in their unit tests or include it in this PR ? If a follow up is desired, I will create an issue to make sure we keep track of it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Worth an issue to track this, probably not a PR you'll get to implement in the next two weeks, but just having an issue that documents the limitation / future feature is good enough for now 🙂

Copy link
Member Author

Choose a reason for hiding this comment

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

Mentioned this in issue #66 :)

* @return Effect on downstream dependencies.
*/
private int effectOnDownstreamDependencies(Fix fix, Set<Location> fixesLocation) {
MethodImpact status = fetchStatus(fix);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why status and not just: MethodImpact methodImpact = fetchMethodImpactForFix(...)? (renaming the fetchStatus method too)

Copy link
Member Author

Choose a reason for hiding this comment

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

Left over from old names/design, thanks for noticing this. 0b5e623


@Override
public int computeLowerBoundOfNumberOfErrors(Set<Fix> tree) {
Set<Location> fixesLocation =
Copy link
Collaborator

Choose a reason for hiding this comment

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

fixLocations, I think.

Copy link
Member Author

Choose a reason for hiding this comment

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


@Override
public List<Error> getTriggeredErrors(Fix fix) {
// We currently only store impact of methods on downstream dependencies.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Might be worth having an issue to track this for arguments/fields and link it here. Though I think that's a fairly low priority issue to solve right now, it's worth documenting the limitation and making sure we remember it's there 🙂

Copy link
Member Author

Choose a reason for hiding this comment

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

Created an issue #66. :)

@@ -44,27 +44,32 @@ public void nullableFlowDetectionEnabledTest() {
coreTestHelper
Copy link
Collaborator

Choose a reason for hiding this comment

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

So, should the test cases requested here be part of this PR or are they pending some other modification from the other half of the PR? (Note that I am interested in seeing what would happen with those simple test cases, without necessarily adding five return null branches like suggested in #62. Happy to see both types of test cases, but the simple cases would be illustrative)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes that case is also covered in this approach. It has an accurate mechanism for updating states after each injection or within measurements. Added the unit test :) 838fad7

@nimakarimipour
Copy link
Member Author

Hi @lazaroclapp, thank you very much for the review, I resolved your comments and left a question. This is ready for another review. Thanks.

Copy link
Collaborator

@lazaroclapp lazaroclapp left a comment

Choose a reason for hiding this comment

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

Let's briefly discuss the ImmutableSet/ImmutableList question in our meeting, but otherwise the changes look good to me 🙂

Copy link
Collaborator

@lazaroclapp lazaroclapp left a comment

Choose a reason for hiding this comment

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

🚀

@nimakarimipour
Copy link
Member Author

🚀

Thank you very much for the review, I created all the requested issue. Will land this now. 🙂

@nimakarimipour nimakarimipour merged commit c824d26 into master Sep 7, 2022
@nimakarimipour nimakarimipour deleted the nimak/issue-64 branch September 7, 2022 21:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Treat impacted parameters as triggered fixes.
2 participants