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

Generic/UnnecessaryStringConcat: improve code coverage #558

Conversation

rodrigoprimo
Copy link
Contributor

@rodrigoprimo rodrigoprimo commented Jul 16, 2024

Description

This PR improves code coverage for the Generic.Strings.UnnecessaryStringConcat sniff.

It also removes two unreachable conditions. I'm a bit hesitant about the condition removed in e1ad905. As far as I can check, there is no T_STRING_CONCAT token in the JS tokenizer. That being said, I don't have a lot of experience with this part of the code, so I might be missing something.

While working on this PR, I noticed that the sniff doesn't support heredoc and nowdoc and I'm inclined to think that it should as it is possible to concatenate strings specified using those two ways (https://www.php.net/manual/en/language.types.string.php). Should I open an issue for this?

Related issues/external references

Part of #146

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
    • This change is only breaking for integrators, not for external standards or end-users.
  • Documentation improvement

PR checklist

  • I have checked there is no other PR open for the same change.
  • I have read the Contribution Guidelines.
  • I grant the project the right to include and distribute the code under the BSD-3-Clause license (and I have the right to grant these rights).
  • I have added tests to cover my changes.
  • I have verified that the code complies with the projects coding standards.
  • [Required for new sniffs] I have added XML documentation for the sniff.

Copy link
Member

@jrfnl jrfnl left a comment

Choose a reason for hiding this comment

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

Hi @rodrigoprimo, thanks for yet another good PR in this series.

Aside from responding to your questions below, I have only two questions:

  1. I can see that you have added tests with comments before and after the concat operator. 👍
    The sniff currently does not flag unnecessary concatenation with these comments. I wonder if it should though as the concatenation is still unnecessary and as the sniff does not contain a fixer, it wouldn't add extra complexity to the logic to do so.
    What are your thoughts on this ?
  2. Would it be an idea to apply a "bow out early" pattern to the sniff to lower the nesting levels ? (for the condition on line 89/90 and line 92)
    This should also improve the usefullness of the code coverage report as it will show more clearly what paths are covered.

I'm a bit hesitant about the condition removed in e1ad905. As far as I can check, there is no T_STRING_CONCAT token in the JS tokenizer. That being said, I don't have a lot of experience with this part of the code, so I might be missing something.

I think you're right, but am not 100% sure myself (99.8% sure only ;-) ).

Maybe we should play it safe for now ? Knowing that this code will be removed in v4.0 anyway ?

        if ($tokens[$stackPtr]['code'] === T_STRING_CONCAT && $phpcsFile->tokenizerType === 'JS') {
            // JS uses T_PLUS for string concatenation, not T_STRING_CONCAT.
            return;
        } else if ($tokens[$stackPtr]['code'] === T_PLUS && $phpcsFile->tokenizerType === 'PHP') {
            // PHP uses T_STRING_CONCAT for string concatenation, not T_PLUS.
            return;
        }

While working on this PR, I noticed that the sniff doesn't support heredoc and nowdoc and I'm inclined to think that it should as it is possible to concatenate strings specified using those two ways (https://www.php.net/manual/en/language.types.string.php). Should I open an issue for this?

Opening an issue about this sounds good. IMO this would be a low priority feature request though.

I have a feeling that kind of code is rare anyhow and handling it correctly would require a non-trivial fix as heredocs/nowdocs are tokenized quite differently from single/double quoted strings.

Doing this to be able to create tests with syntax errors on separate
files.
Both in PHP and JS there is not a scenario where there is no non-empty
token before T_STRING_CONCAT or T_PLUS. There will always be at least
the T_OPEN_TAG token. So checking if `$prev` is `false` is not necessary.
`$prev` will never be `false`.
Also removes `?>` from the end of UnnecessaryStringConcatUnitTest.1.inc
as this token was not relevant for the tests.
…arly

This commit implements an small improvement suggested by @jrfnl during
the PR review. It changes two conditions to adopt a bowing out early
strategy to lower the nesting levels.
This commit simplifies a condition and improves code readability by
reducing its nesting level. It also adds code comments, making
the reason for each of the two remaining checks explicit.
@rodrigoprimo rodrigoprimo force-pushed the test-coverage-unnecessary-string-concat branch from 9e37c3d to 0b4f97e Compare July 18, 2024 14:36
@rodrigoprimo
Copy link
Contributor Author

Thanks for checking this PR, @jrfnl!

The sniff currently does not flag unnecessary concatenation with these comments. I wonder if it should though as the concatenation is still unnecessary and as the sniff does not contain a fixer, it wouldn't add extra complexity to the logic to do so.
What are your thoughts on this ?

I considered this, but I thought that in some rare cases, the concatenation might be intentional precisely to have comments documenting just part of a string. That is why I'm more inclined to think that we should keep the current behavior.

Would it be an idea to apply a "bow out early" pattern to the sniff to lower the nesting levels ? (for the condition on line 89/90 and line 92)
This should also improve the usefullness of the code coverage report as it will show more clearly what paths are covered.

I attempted to implement your suggestion in 9e37c3d. Could you please take a look to check if that is what you had in mind?

I think you're right, but am not 100% sure myself (99.8% sure only ;-) ).
Maybe we should play it safe for now ? Knowing that this code will be removed in v4.0 anyway ?

Makes sense to me. I dropped the original commit and added a new one implementing your suggestion.

Opening an issue about this sounds good. IMO this would be a low priority feature request though.
I have a feeling that kind of code is rare anyhow and handling it correctly would require a non-trivial fix as heredocs/nowdocs are tokenized quite differently from single/double quoted strings.

I share your feeling that that kind of code is rare. Considering this, I'm more inclined not to open an issue. We can revisit this if a user ever comes across this limitation in the sniff and reports it. How does that sound?

@jrfnl
Copy link
Member

jrfnl commented Jul 19, 2024

The sniff currently does not flag unnecessary concatenation with these comments. I wonder if it should though as the concatenation is still unnecessary and as the sniff does not contain a fixer, it wouldn't add extra complexity to the logic to do so.
What are your thoughts on this ?

I considered this, but I thought that in some rare cases, the concatenation might be intentional precisely to have comments documenting just part of a string. That is why I'm more inclined to think that we should keep the current behavior.

Hmm.. still not sure about this (in that case a multi-line concatenation with comment could be used with the allowMultiline property to have the comment and still have clean code) , but this question not a blocker for this PR. Let's leave this for now.

Would it be an idea to apply a "bow out early" pattern to the sniff to lower the nesting levels ? (for the condition on line 89/90 and line 92)

I attempted to implement your suggestion in 9e37c3d. Could you please take a look to check if that is what you had in mind?

Looks fine to me.

Opening an issue about this sounds good. IMO this would be a low priority feature request though.
I have a feeling that kind of code is rare anyhow and handling it correctly would require a non-trivial fix as heredocs/nowdocs are tokenized quite differently from single/double quoted strings.

I share your feeling that that kind of code is rare. Considering this, I'm more inclined not to open an issue. We can revisit this if a user ever comes across this limitation in the sniff and reports it. How does that sound?

That's fair.

@jrfnl jrfnl added this to the 3.10.x Next milestone Jul 19, 2024
@jrfnl jrfnl merged commit eb3454f into PHPCSStandards:master Jul 19, 2024
40 checks passed
@rodrigoprimo rodrigoprimo deleted the test-coverage-unnecessary-string-concat branch October 22, 2024 13:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants