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

[java] SingularField false positive with switch in method that both assigns and reads field #174

Closed
theneva opened this issue Jan 3, 2017 · 5 comments
Labels
a:false-positive PMD flags a piece of code that is not problematic
Milestone

Comments

@theneva
Copy link

theneva commented Jan 3, 2017

Affects PMD Version: 5.5.1...6.55.0

Rule: SingularField

Description:

I have the following JAX-RS event listener that uses a Prometheus Summary to measure the time of all non-404 responses. It violates the java/design/SingularField rule.

Code Sample demonstrating the issue:

// package, imports

@Provider
public class LatencyRequestEventListener implements RequestEventListener {
    private static final Summary SUMMARY_LATENCY_SECONDS = …;

    private final ResourceInfo resourceInfo;

    private Summary.Timer timer; // BREAKS HERE

    LatencyRequestEventListener(final ResourceInfo resourceInfo) {
        this.resourceInfo = resourceInfo;
    }

    @Override
    public void onEvent(final RequestEvent event) {
        switch (event.getType()) {
            case RESOURCE_METHOD_START:
                final ResourceMethod matchedResourceMethod = event.getUriInfo().getMatchedResourceMethod();

                if (matchedResourceMethod == null) {
                    return;
                }

                timer = SUMMARY_LATENCY_SECONDS // ASSIGN FIELD
                    .labels(
                        matchedResourceMethod.getHttpMethod()
                        , resourceInfo.getResourceClass().getSimpleName() + "." + resourceInfo.getResourceMethod().getName()
                    )
                    .startTimer();
                break; // Don't keep going (both cases cannot be reached in the same call)
            case FINISHED:
                if (timer != null) {
                    timer.observeDuration(); // READ FIELD
                }
        }
    }
}

Expected outcome:

PMD reports a violation at line 25, but that's wrong. That's a false positive.

This results in the following error:

/path/to/project/…/listeners/LatencyRequestEventListener.java:25: Perhaps 'timer' could be replaced by a local variable.

timer can't be a local variable, so I don't think it's correct to report this rule violated.

I understand that the rule is violated if a field is only accessed by a single method. I also acknowledge that having the same method be called twice to first assign a field (the RESOURCE_METHOD_START case) and then read the field (FINISHED) may not be a good design. However, that's how the JAX-RS people designed the RequestEventListener class.

If I pull the code for the RESOURCE_METHOD_START case into a separate method, it passes with no problem since multiple methods access the field.

Is this a bug, or am I doing something wrong?

EDIT: As a funky side note, pulling the configuration of the Timer into a method makes the code legal, despite still only referencing the timer field in onEvent(…):

private static Summary.Child configureTimer(
    final Summary summary,
    final String httpMethod
    , final String handlerName
) {
    return summary
        .labels(httpMethod, handlerName);
}

@Override
public void onEvent(final RequestEvent event) {
    switch (event.getType()) {
        case RESOURCE_METHOD_START:
            final ResourceMethod matchedResourceMethod = event.getUriInfo().getMatchedResourceMethod();
            if (matchedResourceMethod != null) {
                timer = configureTimer(
                    SUMMARY_LATENCY_SECONDS,
                    matchedResourceMethod.getHttpMethod()
                    , resourceInfo.getResourceClass().getSimpleName() + "." + resourceInfo.getResourceMethod().getName()
                ).startTimer();
            }
            break;
        case FINISHED:
            if (timer != null) {
                timer.observeDuration();
            }
    }
}
@jsotuyod
Copy link
Member

jsotuyod commented Jan 3, 2017

Hi @theneva and thanks for your report!

You are absolutely right, this is a false positive, mostly down to the fact PMD can't tell how calls will be performed in time.

However, I believe we could improve this scenario by checking, not only that the field is only being written / read on a single method, but is actually being written in all branches before being read (and therefore not relying on previously set values from other calls). This however, would probably need to rely on our Data Flow Analysis framework, which is in serious need of a revamp.

This is definitely in our backlog, but will take some time to get fixed. In the meantime you can either suppress the warning locally and document it as a false positive with a comment even linking back to this issue if you would like so.

@theneva
Copy link
Author

theneva commented Jan 3, 2017

Hey @jsotuyod, thanks for the reply! I just realised I was supposed to file the bug report on SourceForge, so I did that: https://sourceforge.net/p/pmd/bugs/1558/

I'll close this issue here. Thanks again :)

@theneva theneva closed this as completed Jan 3, 2017
@jsotuyod
Copy link
Member

jsotuyod commented Jan 3, 2017

@theneva don't worry, we have decided to move away from SourceForge issues and into GitHub. We will eventually move all issues here anyway.

@theneva
Copy link
Author

theneva commented Jan 3, 2017

Oh, cool! I'll leave it open in both places then.

@theneva theneva reopened this Jan 3, 2017
@adangel adangel changed the title SingularField rule incorrectly reported violated with switch in method that both assigns and reads field [java] SingularField rule incorrectly reported violated with switch in method that both assigns and reads field Jan 5, 2017
@jsotuyod jsotuyod added the a:bug PMD crashes or fails to analyse a file. label Jan 8, 2017
@jsotuyod jsotuyod added a:false-positive PMD flags a piece of code that is not problematic and removed a:bug PMD crashes or fails to analyse a file. labels Aug 15, 2017
@adangel adangel added this to the 7.0.0 milestone Jan 12, 2024
@adangel
Copy link
Member

adangel commented Jan 12, 2024

This has been fixed in PMD 7.

@adangel adangel changed the title [java] SingularField rule incorrectly reported violated with switch in method that both assigns and reads field [java] SingularField false positive with switch in method that both assigns and reads field Jan 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:false-positive PMD flags a piece of code that is not problematic
Projects
None yet
Development

No branches or pull requests

3 participants