-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
PHP 7 return type tokenize #1527
Comments
If I tokenized it as T_RETURN_TYPE, sniffs testing namespaces wouldn't be able to find it. If I gave it a new special type of token, sniffs could listen for it as well, but would have to separate out the namespace themselves when finding it. This would also be a BC break. The main reason T_RETURN_TYPE was added in the first place was to ensure sniffs listening for T_ARRAY wouldn't pick up the token. I had to give it a new token type, so I picked that one. If a sniff wants to check the placement of the return type, or the fact it exists, they should listen for T_FUNCTION and look for the T_COLON before the return type. |
@gsherwood yesterday I've played with it a bite more and finally I think it's fine (at least for and my cases). I've developed following sniff: If you'd like I can create PR to PHP_CodeSniffer if you want include this sniff into this library. What do you think? Thanks! |
Spent about an hour trying to figure out what was wrong with a test. Was expecting T_RETURN_TYPE to be the full type string. A decent solution I think would be if getMethodProperties gave me the full return type as a string. |
Just want to be clear that this is the feature I'll be looking to implement in 3.3.0 and not changing how the return types are tokenized. |
I've changed my mind. Given that this is valid code: class Foo {
function myFunction(): \ MyNamespace \
/*comment*/MyClass \
Bar {}
} I think developers are going to need the extra help from the tokenizer. I'll still include the return type in |
… + the return value of File::getMethodProperties() now contains a return_type array index with a cleaned up return type (ref #1527)
I've now committed the change that will tokenize the entire namespaced return type as a single If the return type is nullable, the As this change manipulates the token array at a very low level, I had to move the code that detects return types from the second pass to the first pass in the tokenizer, which changes the way detection happens. All tests are passing (including new ones) but it could use more testing from anyone who is able to. |
I've checked it on the following example: function hello() : \MyNamespace // hey
\Something # hello
\Here /** hola */ \MyInterface {} and I'm getting:
so as you can see it's not a single |
That's correct. PHPCS splits all multi-line tokens like that. The If you want to ensure developers are not splitting namespaced return values over multiple lines, you can just check to ensure there is a single |
I'm a bit apprehensive about this change as - based on the finding from @webimpress - you will no longer be able to detect (and forbid) comments being used within return type declarations as the comments are now tokenized as part of the return type which feels very counter-intuïtive to me. If I'm honest, I would have expected just the change to the |
In addition to the above:
Also, - again based on what I've read here -, I suspect that:
|
I'm agree with @jrfnl. Just tried to adjust my sniff to work with current behaviour and it's so complicated, because we have comments in T_RETURN_TYPE and multiple T_RETURN_TYPE for one function. The second is fine, we can have multiple T_RETURN_TYPE for one function, but I don't like including comments into the content. I think we should either:
Changes to |
I thought this is exactly what you asked for. So what about T_WHITESPACE, T_COMMENT etc all remain as those tokens, but all other parts of the return type become T_RETURN_TYPE. So if you do what I imagine the vast vast majority of developers will do (no whitepsace, no comments) then you end up with one T_RETURN_TYPE token. If you go crazy and fill the return type with rubbish, you get a mix of whitespace/comments/return type tokens. The So the major change is that T_STRING and T_NS_SEPARATOR tokens will now be combined into T_RETURN_TYPE tokens instead of being left as they are. Thoughts? |
@gsherwood When I created that issue I haven't considered comments and whitespaces in return type. I thought it is not allowed and PHP parser will raise an exception. As I said in #1527 (comment) I've managed to write a sniff working with |
@gsherwood I've created PR #1994 with reverted changes to the tokenizer, all tests are fine. Function |
I'm not going to revert this change. I'll probably just change it to how I described things working in my last comment because I don't like the idea of the last bit of a namespace being tokenised as T_RETURN_TYPE and the rest of it as T_STRING. I also don't like the idea of a class name without a namespace being tokenized as T_RETURN_TYPE, making it different to a namespaced one. The testing I did made me realise it is not consistent, so it needs to change. |
I've made the change I was talking about. So in that sample code: <?php
function hello() : \MyNamespace // hey
\Something # hello
\Here /** hola */ \MyInterface {} Instead of the return type being tokenised like this:
It is now tokenized like this:
Which is still a mess, but a mess because someone decided to put comments and whitespace inside a namespaced return type. I don't even know why that is valid code, but I think it's pretty easy to detect now given you can just look for T_RETURN_TYPE, and if you find another T_RETURN_TYPE before the end of the definition, it's a dirty value. If you want comments inside your return type strings, you can do that now and they will be checked properly. If you want newlines inside your return type string, you can do that now and the newline char will be checked. If you want namespaced return types to be split up and indented, you can write a sniff to check that now. Anything thoughts from anyone on this change? |
Forgot to mention that the (hopefully) more normal way of writing the return type: <?php
function hello() : \MyNamespace\Something\Here\MyInterface {} Will now get tokenized like this:
Which was the original request, and replaces the existing behaviour that tokenized it like this:
|
I'm definitely a lot happier with the new version. Thank you @gsherwood. AFAICS, there still one of my previously raised concerns remaining unaddressed:
This is about code like:
|
This is true, and was my original concern with doing this. But I don't think it is overly hard to check now that all whitespace and comments are tokenized individually. So that same code will be tokenized like this:
So it's a matter of also looking for T_RETURN_TYPE and seeing if it contains a It's the same sort of thing when using namespace separators inside strings: $method = '\ NSName \ NSSubName \ ClassName :: foo';
call_user_func($method); Although that would be a far harder sniff to write. |
@gsherwood Thanks for your response. I guess that's doable, though it still requires to sniff for an additional - non-intuitive - token. |
@gsherwood Now it works for me. Thanks! However I'm not sure if my original request was valid. I've changes my sniffs to work with multiple T_RETURN_TYPE tokens and I can do everything with it, it is just not obvious that we have more tokens included in one token (I mean T_NS_SEPARATOR and T_STRING). Maybe it should be revisited in v4. Thoughts? |
I can remove both T_ARRAY_HINT and T_RETURN_TYPE, which were both there to stop "array" strings from being tokenized as T_ARRAY. That also means that T_SELF/T_PARENT etc used for return types will revert back to those tokens from the T_RETURN_TYPE tokens that they currently are. |
I've removed T_ARRAY_HINT because it didn't make sense for it to have its own token but all other type hints remained as normal tokens. So with that done, it probably doesn't make sense to have special tokens for T_RETURN_TYPE either. The one thing that needs doing in there is to ensure "array" is converted to T_STRING so it is not found by array sniffs. |
I've removed T_RETURN_TYPE completely and ensured that "array" strings in there are now T_STRING. You'll need to figure out the return type start position and string manually from now on, or use getMethodProperties if you just want the cleaned up version of the return type. I've kept all the conversion code in the first pass of the tokenizer because I have a suspicion that I may need to do more mucking around with this area in the future. Anyone have have thoughts about this change? I don't think I'll change my mind again, but open to attempts. |
@gsherwood These changes make total sense to me. While it will be a pain to adjust existing sniffs to deal with PHPCS cross-version compat for this (for external standards which support more than just the latest & greatest PHPCS), I think this makes the whole function declaration tokenizing more consistent and stable for the future. A test run on WPCS shows no breaks so far, which is not surprising as WP still supports PHP 5.2, so not many - if any - sniffs take type declarations into account. However, as could be expected, a test run on PHPCompatibility shows quite some breakage, at least five sniffs will need adjusting. |
Thanks a lot. |
@gsherwood I had a look on my sniffs and all seems to be fine, I need to do couple small changes, but in general it works, and I'm happy with that solution. So just to note it here function/closure return type declaration can contain: Thanks a lot for all of these changes, @gsherwood ! |
@webimpress Thanks. We got there in the end. I'll leave this open until @jrfnl has had a chance to check the impact on PHPCompatibility and see if any more changes are suggested. |
FYI: I've been down & out with the flu for the last three days (and still not well). Once my brain is working again, this is on my list. |
:( Hope you feel better soon. |
In the mean time, I've had a look at this for PHPCompatibility & got things working again for that standard - PR is open: PHPCompatibility/PHPCompatibility#642 I haven't verified WPCS yet, but expect no problems. |
Thanks @jrfnl. I'll close this off now. |
In PHP 7 we can declare return type for method:
In this case "int" is tokenized as
T_RETURN_TYPE
and it's fine.We can also declare there complex type:
and in the second case I think it is wrong tokenized, because we have there:
\
-T_NS_SEPARATOR
MyNamespace
-T_STRING
\
-T_NS_SEPARATOR
MyClass
-T_RETURN_TYPE
so we have 4 tokens, but I would expect only one:
T_RETURN_TYPE
with content\MyNamespace\MyClass
. What do you think?The text was updated successfully, but these errors were encountered: