-
-
Notifications
You must be signed in to change notification settings - Fork 112
Generic/LineLength: use different warning and errors for namespaced names #1367
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
base: 4.x
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -177,21 +177,62 @@ protected function checkLineLength(File $phpcsFile, array $tokens, int $stackPtr | |
| if ($this->absoluteLineLimit > 0 | ||
| && $lineLength > $this->absoluteLineLimit | ||
| ) { | ||
| $code = 'MaxExceeded'; | ||
| if ($this->isNamespacedNameExceedingLength($tokens, $stackPtr, $this->absoluteLineLimit) === true) { | ||
| $code = 'NamespacedNameMaxExceeded'; | ||
| } | ||
|
|
||
| $data = [ | ||
| $this->absoluteLineLimit, | ||
| $lineLength, | ||
| ]; | ||
|
|
||
| $error = 'Line exceeds maximum limit of %s characters; contains %s characters'; | ||
| $phpcsFile->addError($error, $stackPtr, 'MaxExceeded', $data); | ||
| $phpcsFile->addError($error, $stackPtr, $code, $data); | ||
| } elseif ($lineLength > $this->lineLimit) { | ||
| $code = 'TooLong'; | ||
| if ($this->isNamespacedNameExceedingLength($tokens, $stackPtr, $this->lineLimit) === true) { | ||
| $code = 'NamespacedNameTooLong'; | ||
| } | ||
|
|
||
| $data = [ | ||
| $this->lineLimit, | ||
| $lineLength, | ||
| ]; | ||
|
|
||
| $warning = 'Line exceeds %s characters; contains %s characters'; | ||
| $phpcsFile->addWarning($warning, $stackPtr, 'TooLong', $data); | ||
| $phpcsFile->addWarning($warning, $stackPtr, $code, $data); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| /** | ||
| * Checks if a line is a namespaced name | ||
| * | ||
| * @param array $tokens The token stack. | ||
| * @param int $stackPtr The last token on the line. | ||
| * @param int $lineLimit The line limit. | ||
| * | ||
| * @return bool | ||
| */ | ||
| private function isNamespacedNameExceedingLength(array $tokens, int $stackPtr, int $lineLimit): bool | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would suggest naming |
||
| { | ||
| $line = $tokens[$stackPtr]['line']; | ||
|
|
||
| for ($i = $stackPtr; $tokens[$i]['line'] === $line; $i--) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a bit of an edge case, but I think the code should protect against it. Consider the following code (note that the code is on the first line together with the PHP opening tag): <?php $result = doSomething($arg1, $arg2, $arg3, $arg4, $arg5, $arg6, \Short\Ns\myFunction($arg7));It generates two warnings as this loop tries to access Undefined array key -1 |
||
| $length = ($tokens[$i]['column'] + $tokens[$i]['length'] - 1); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is still not correct. The code checks whether the token's end column position exceeds $result = doSomething($arg1, $arg2, $arg3, $arg4, $arg5, $arg6, \Short\Ns\myFunction($arg7));I believe the code should check simply if the length of the current token exceeds
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you have suggestions on how to deal with this? Since things like the following might also be a situation where we want to trigger the NamespacedNameTooLong warning: $foobarVariableName = new \Long\Ns\Long\Ns\Long\Ns\Long\Ns\Long\Ns\Long\Ns\Long\Ns\Long\Ns($arg)That was the reason for checking the column length.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding of @jrfnl's suggestion is that the code sample you provided should not trigger the Does that help clarify things? What do you think? |
||
|
|
||
| // Check the line limit of the namespaced name is equal or over the line length. This check accounts for the | ||
| // fact that namespaced names are or closed by ; or opened by ( or {. | ||
|
Comment on lines
+225
to
+226
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment doesn't seem accurate.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Honest question: What is not accurate about it?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe I'm missing/misunderstanding something, but to me it reads a bit confusingly (and it could be because I'm not a native English speaker). What is the "line limit of the namespaced name"? I guess the check is against the "line length limit" and not the "line length". And as far as I can understand, the second sentence isn't accurate since namespaced names can appear in many more contexts beyond That said, if the logic changes per the other discussion, this comment will need to be rewritten anyway, so no need to worry about it for now. |
||
| if ($length >= $lineLimit | ||
| && ($tokens[$i]['code'] === T_NAME_QUALIFIED | ||
| || $tokens[$i]['code'] === T_NAME_FULLY_QUALIFIED | ||
| || $tokens[$i]['code'] === T_NAME_RELATIVE) | ||
| ) { | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| <?php | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A few thoughts on the tests: Some of the test cases seem redundant to me. For example, lines 13-15 test On the other hand, some scenarios that exercise different code paths are missing. For example:
Maybe there could be more variation as well using namespace tokens in other contexts (like type hints, |
||
|
|
||
| // This is just within the limit | ||
| namespace This\Name\Space\IsGoingToBeJustWithinLimits\LongLongLongLongLongLoong; | ||
|
|
||
| // This is just within the absolute limit and should throw a NamespacedNameTooLong warning | ||
| namespace This\Name\Space\IsGoingToBeJustWithinLimits\LongLongLongLongLongLongLongLongLongLongLongLongLongLongLoooooong; | ||
|
|
||
| // This is too long and should throw a NamespacedNameMaxExceeded error | ||
| namespace This\Name\Space\IsGoingToBeTooLong\LongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLoooong; | ||
|
|
||
| // These are just within the limits | ||
| use ThisReallyLong\Looooooooooooooong\UseStatement\ShouldBeNotTooLong\ClassName; | ||
| use function ThisReallyLong\Looong\UseStatement\ShouldBeNotTooLong\functionCall; | ||
| use const ThisReallyLong\Loooooooooong\UseStatement\ShouldBeNotTooLong\CONSTANT; | ||
|
|
||
| // These are just a bit too long and should throw a NamespacedNameTooLong warning | ||
| use ThisReallyLong\Long\Looooong\Looooooooooooooong\UseStatement\ThatShouldThrowAWarning\BecauseItsNotTooLong\ClassName; | ||
| use function ThisReallyLong\Long\Looooooong\Long\UseStatement\ThatShouldThrowAWarning\BecauseItsNotTooLong\functionCall; | ||
| use const ThisReallyLong\Long\Looooong\Loooooooooong\UseStatement\ThatShouldThrowAWarning\BecauseItsNotTooLong\CONSTANT; | ||
|
|
||
| // These are just a bit too long and should throw a NamespacedNameMaxExceeded error | ||
| use ThisReallyLong\Long\Loooooong\Looooong\UseStatement\ThatShouldNotBeAllowed\AndThrowErrorsBecauseItsTooLong\ClassName; | ||
| use function ThisReallyLong\Long\Looong\UseStatement\ThatShouldNotBeAllowed\AndThrowErrorsBecauseItsTooLong\functionCall; | ||
| use const ThisReallyLong\Long\Loooooooooong\UseStatement\ThatShouldNotBeAllowed\AndThrowErrorsBecauseItsTooLong\CONSTANT; | ||
|
|
||
| // These are just within the limits | ||
| echo \This\Name\Space\IsGoingToBeJustWithinLimits\LongLongLooong\functionCall(); | ||
| new \This\Name\Space\IsGoingToBeJustWithinLimits\LongLongLongLooong\ClassName(); | ||
|
|
||
| // These are just a bit too long and should throw a NamespacedNameTooLong warning | ||
| echo \ThisReallyLong\Long\Looooong\Loooooooong\UseStatement\ThatShouldThrowAWarning\BecauseItsNotTooLong\functionCall(); | ||
| new \ThisReallyLong\Long\Looooong\Loooooooooooong\UseStatement\ThatShouldThrowAWarning\BecauseItsNotTooLong\ClassName(); | ||
|
|
||
| // These are just a bit too long and should throw a NamespacedNameMaxExceeded error | ||
| echo \ThisReallyLong\Long\Long\Looooong\UseStatement\ThatShouldNotBeAllowed\AndThrowErrorsBecauseItsTooLong\functionCall(); | ||
| new \ThisReallyLong\Long\Long\Looooooooong\UseStatement\ThatShouldNotBeAllowed\AndThrowErrorsBecauseItsTooLong\ClassName(); | ||
|
|
||
| // These are a bit too long but can be shortened and should throw a TooLong warning | ||
| echo \This\Name\Space\IsGoingToBeJustWithinLimits\LongLongLooong\functionCall('foo', 'bar', 'baz'); | ||
| new \This\Name\Space\IsGoingToBeJustWithinLimits\LongLongLongLooong\ClassName('foo', 'bar', 'baz'); | ||
|
|
||
| // These are just a bit too long but can be shortened and should throw a MaxExceeded error | ||
| echo \ThisReallyLong\Long\Long\Looong\UseStatement\ThatShouldNotBeAllowed\AndThrowErrorsBecauseItsTooLong\functionCall('foo', 'bar', 'baz'); | ||
| new \ThisReallyLong\Long\Long\Looooooong\UseStatement\ThatShouldNotBeAllowed\AndThrowErrorsBecauseItsTooLong\ClassName('foo', 'bar', 'baz'); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that the method changed the description needs to be updated.