PHP function list and abstract functions
-
An another problem, is the heredoc in php. In some case, a class can not appear in the treeview.
An example of faulty heredoc :
function SocialTwitterPlugin() { return <<<XXCC <a href="https://twitter.com/share" class="twitter-share-button" data-via="TutoInformatik" data- size="large">Tweet</a> <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s) [0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)) {js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}} (document, 'script', 'twitter-wjs');</script> XXCC; }
perhaps heredoc could be handle like comment ?
-
-
See https://github.com/notepad-plus-plus/notepad-plus-plus/pull/3393, @MAPJe71 has a expertise for functionlist changes.
-
For the problem with heredoc in php
<parser id ="php_syntax" displayName="PHP" commentExpr="(?s:/\*.*?\*/)|(?m-s://.*?$)" >
I have changed it into
<parser id ="php_syntax" displayName="PHP" commentExpr="\x3C{3}[\x20\t]*(\w+)(\r|\n|\r\n)(.|[\s])*?\1;(\r|\n|\r\n)|(?s:/\*.*?\*/)|(?m-s://.*?$)" >
seems to work.
-
@Florent-Pagès could you try this:
commentExpr="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?s:\x2F\x2A.*?\x2A\x2F) # Multi Line Comment | (?m-s:(?:\x23|\x2F{2}).*$) # Single Line Comment 1 and 2 | (?s:\x22(?:[^\x22\x24\x5C]|\x5C.)*\x22) # String Literal - Double Quoted | (?s:\x27(?:[^\x27\x5C]|\x5C.)*\x27) # String Literal - Single Quoted | (?: # Here Document \x3C{3}(?'HDID'[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*)[^\r\n]*(?:\r?\n|\n?\r) (?s:.*?) (?:\r?\n|\n?\r)\k'HDID' # close with exactly the same identifier, in the first column ) | (?: # Now Document \x3C{3}\x27(?'NDID'[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*)\x27[^\r\n]*(?:\r?\n|\n?\r) (?s:.*?) (?:\r?\n|\n?\r)\k'NDID' # close with exactly the same identifier, in the first column ) "
-
Seems to work. I will test longer this week.
-
I have found a bad case but not with heredoc, the class does not appear in functionlist :
<?php class Bad { function RsdTitle() { $i = 1; $table = 5; if (TRUE) { switch ($i) { case 1: return "Jeu pour apprendre la table de multiplication par {$table}"; case 2: return "Jeu pour apprendre la table de {$table} d'addition"; } } return "Jeu avec les tables de multiplications https://motsbleus.pages-informatique.com/jeu-tables-multiplications.html"; } } ?>
-
Where to find the regex reference manual used in the functionlist?
-
@Florent-Pagès Please try this parser:
<parser displayName="PHP - Personal Home Page / PHP Hypertext Preprocessor" id ="php_syntax" commentExpr="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?s:\x2F\x2A.*?\x2A\x2F) # Multi Line Comment | (?m-s:(?:\x23|\x2F{2}).*$) # Single Line Comment 1 and 2 | (?s:\x22(?:[^\x22\x24\x5C]|\x5C.)*\x22) # String Literal - Double Quoted | (?s:\x27(?:[^\x27\x5C]|\x5C.)*\x27) # String Literal - Single Quoted | (?: # Here Document \x3C{3}(?'HDID'[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*)[^\r\n]*(?:\r?\n|\n?\r) (?s:.*?) (?:\r?\n|\n?\r)\k'HDID' # close with exactly the same identifier, in the first column ) | (?: # Now Document \x3C{3}\x27(?'NDID'[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*)\x27[^\r\n]*(?:\r?\n|\n?\r) (?s:.*?) (?:\r?\n|\n?\r)\k'NDID' # close with exactly the same identifier, in the first column ) " > <classRange mainExpr ="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?(DEFINE) # definition of sub-routines (?'VALID_ID' \b(?!(?-i: # keywords (case-sensitive), not to be used as identifier a(?:bstract|nd|rray|s) | b(?:ool|reak) | c(?:a(?:llable|se|tch)|l(?:ass|one)|on(?:st|tinue)) | d(?:e(?:clare|fault)|ie|o) | e(?:cho|lse(?:if)?|mpty|nd(?:declare|for(?:each)?|if|switch|while)|val|x(?:it|tends)) | f(?:alse|loat|inal|or(?:each)?|unction) | g(?:lobal|oto) | i(?:f|mplements|n(?:clude(?:_once)?|st(?:anceof|eadof)|t(?:erface)?)|sset) | list | mixed | n(?:amespace|ew|u(?:ll|meric)) | o(?:r|bject) | p(?:r(?:i(?:nt|vate)|otected)|ublic) | re(?:quire(?:_once)?|turn) | s(?:t(?:atic|ring)|witch) | t(?:hrow|r(?:ait|ue|y)) | u(?:nset|se) | var | while | xor | __(?:halt_compiler|(?:CLASS|DIR|F(?:ILE|UNCTION)|LINE|METHOD|NAMESPACE|TRAIT)__) )\b) [A-Za-z_\x7F-\xFF][\w\x7F-\xFF]* # valid character combination for identifiers ) (?'INTERFACE_LIST' \s+(?:\x5C|(?&VALID_ID))+ (?: \s*, \s*(?:\x5C|(?&VALID_ID))+ )* ) ) (?m-i) # ^ and $ match at line-breaks, case-sensitive ^\h* # optional leading white-space at start-of-line (?: (?:(?-i:abstract|final)\s+)? # optional class entry type (?-i:class)\s+ \K # discard text matched so far (?&VALID_ID) # identifier used as class name (?: # optional extends-from-class \s+(?-i:extends) \s+(?:\x5C|(?&VALID_ID))+ )? (?: # optional implements-class/interfaces \s+(?-i:implements) (?&INTERFACE_LIST) )? | (?-i:interface)\s+ \K # discard text matched so far (?&VALID_ID) # identifier used as interface name (?: # optional extends-from list \s+(?-i:extends) (?&INTERFACE_LIST) )? | (?-i:trait)\s+ \K # discard text matched so far (?&VALID_ID) # identifier used as trait name ) \s*\{ " openSymbole ="\{" closeSymbole="\}" > <className> <nameExpr expr="[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*" /> </className> <function mainExpr="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?m-i) # ^ and $ match at line-breaks, case-sensitive ^\h* # optional leading white-space at start-of-line (?:(?-i: # field modifiers p(?:r(?:ivate|otected)|ublic) # - access modifiers | abstract|final|static # - ... )\s+)* # require a white-space separator (?-i:function)\s+ \K # discard text matched so far (?:\x26\s*)? # optionally a reference (?'VALID_ID' # valid identifier, use as subroutine \b(?!(?-i: # keywords (case-sensitive), not to be used as identifier a(?:bstract|nd|rray|s) | b(?:ool|reak) | c(?:a(?:llable|se|tch)|l(?:ass|one)|on(?:st|tinue)) | d(?:e(?:clare|fault)|ie|o) | e(?:cho|lse(?:if)?|mpty|nd(?:declare|for(?:each)?|if|switch|while)|val|x(?:it|tends)) | f(?:alse|loat|inal|or(?:each)?|unction) | g(?:lobal|oto) | i(?:f|mplements|n(?:clude(?:_once)?|st(?:anceof|eadof)|t(?:erface)?)|sset) | list | mixed | n(?:amespace|ew|u(?:ll|meric)) | o(?:r|bject) | p(?:r(?:i(?:nt|vate)|otected)|ublic) | re(?:quire(?:_once)?|turn) | s(?:t(?:atic|ring)|witch) | t(?:hrow|r(?:ait|ue|y)) | u(?:nset|se) | var | while | xor | __(?:halt_compiler|(?:CLASS|DIR|F(?:ILE|UNCTION)|LINE|METHOD|NAMESPACE|TRAIT)__) )\b) [A-Za-z_\x7F-\xFF][\w\x7F-\xFF]* # valid character combination for identifiers ) # identifier used as method name \s*\( # start of function parameters [^{]*\{ # start of function body " > <functionName> <funcNameExpr expr="(?:\x26\s*)?[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*\s*\((?:[^/{]|/(?![*/]))*" /> <!-- comment out the following node to display the method with parameters --> <funcNameExpr expr="(?:\x26\s*)?[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*" /> </functionName> </function> </classRange> <function mainExpr="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?m-i) # ^ and $ match at line-breaks, case-sensitive ^\h* # optional leading white-space at start-of-line (?-i:function)\s+ \K # discard text matched so far (?:\x26\s*)? # optionally a reference (?'VALID_ID' # valid identifier, use as subroutine \b(?!(?-i: # keywords (case-sensitive), not to be used as identifier a(?:bstract|nd|rray|s) | b(?:ool|reak) | c(?:a(?:llable|se|tch)|l(?:ass|one)|on(?:st|tinue)) | d(?:e(?:clare|fault)|ie|o) | e(?:cho|lse(?:if)?|mpty|nd(?:declare|for(?:each)?|if|switch|while)|val|x(?:it|tends)) | f(?:alse|loat|inal|or(?:each)?|unction) | g(?:lobal|oto) | i(?:f|mplements|n(?:clude(?:_once)?|st(?:anceof|eadof)|t(?:erface)?)|sset) | list | mixed | n(?:amespace|ew|u(?:ll|meric)) | o(?:r|bject) | p(?:r(?:i(?:nt|vate)|otected)|ublic) | re(?:quire(?:_once)?|turn) | s(?:t(?:atic|ring)|witch) | t(?:hrow|r(?:ait|ue|y)) | u(?:nset|se) | var | while | xor | __(?:halt_compiler|(?:CLASS|DIR|F(?:ILE|UNCTION)|LINE|METHOD|NAMESPACE|TRAIT)__) )\b) [A-Za-z_\x7F-\xFF][\w\x7F-\xFF]* # valid character combination for identifiers ) # identifier used as function name \s*\( # start of function parameters [^{]*\{ # start of function body " > <functionName> <nameExpr expr="(?:\x26\s*)?[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*\s*\((?:[^/{]|/(?![*/]))*" /> <!-- comment out the following node to display the function with its parameters --> <nameExpr expr="(?:\x26\s*)?[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*" /> </functionName> </function> </parser>
-
Not working in this case but i focus on the problem : the “$i” in the switch/case.
<?php class Bad { function RsdTitle() { $i = 1; switch ($i) { case 1: $a = "$i"; break; } return "1"; } } ?>
So i tried to change your parser in the commentExpr this way :
# orignal line-> | (?s:\x22(?:[^\x22\x24\x5C]|\x5C.)*\x22) # String Literal - Double Quoted | (?s:\x22(?:[^\x22\x5C]|\x5C.)*\x22) # String Literal - Double Quoted
It seem to work for me but i am not sure of what i did. (the \x24 is $ caracter)
-
The original regex would not consider
"$i"
a double quoted string literal. That’s incorrect (my bad), your adaption is correct. -
Thanks a lot, it works great !
I hope it will be included into the next release.
-
I will include it in Function List Update 4.
-
Super. Functions list is very useful for me.
I hope “functions list” will be improved: showing line number , jumping on class name or synch selection on edit location.
-
I have change a line in functionList.xml in the php parser :
# Old line: [^{]*\{ # start of function body (?:[^{;]*(?:\{|;)) # start of function body
It fixes the problem that an abstract function doesn’t have body.
-
full PHP parser
<!-- ========================================================= [ PHP ] --> <!-- PHP - Personal Home Page / PHP Hypertext Preprocessor --> <parser displayName="PHP - Personal Home Page / PHP Hypertext Preprocessor" id ="php_syntax" commentExpr="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?s:\x2F\x2A.*?\x2A\x2F) # Multi Line Comment x2F -> '/' x2A -> '*' | (?m-s:(?:\x23|\x2F{2}).*$) # Single Line Comment 1 # and 2 // # | (?s:\x22(?:[^\x22\x24\x5C]|\x5C.)*\x22) # String Literal - Double Quoted | (?s:\x22(?:[^\x22\x5C]|\x5C.)*\x22) # String Literal - Double Quoted | (?s:\x27(?:[^\x27\x5C]|\x5C.)*\x27) # String Literal - Single Quoted | (?: # Here Document \x3C{3}(?'HDID'[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*)[^\r\n]*(?:\r?\n|\n?\r) (?s:.*?) (?:\r?\n|\n?\r)\k'HDID' # close with exactly the same identifier, in the first column ) | (?: # Now Document \x3C{3}\x27(?'NDID'[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*)\x27[^\r\n]*(?:\r?\n|\n?\r) (?s:.*?) (?:\r?\n|\n?\r)\k'NDID' # close with exactly the same identifier, in the first column ) " > <classRange mainExpr ="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?(DEFINE) # definition of sub-routines (?'VALID_ID' \b(?!(?-i: # keywords (case-sensitive), not to be used as identifier a(?:bstract|nd|rray|s) | b(?:ool|reak) | c(?:a(?:llable|se|tch)|l(?:ass|one)|on(?:st|tinue)) | d(?:e(?:clare|fault)|ie|o) | e(?:cho|lse(?:if)?|mpty|nd(?:declare|for(?:each)?|if|switch|while)|val|x(?:it|tends)) | f(?:alse|loat|inal|or(?:each)?|unction) | g(?:lobal|oto) | i(?:f|mplements|n(?:clude(?:_once)?|st(?:anceof|eadof)|t(?:erface)?)|sset) | list | mixed | n(?:amespace|ew|u(?:ll|meric)) | o(?:r|bject) | p(?:r(?:i(?:nt|vate)|otected)|ublic) | re(?:quire(?:_once)?|turn) | s(?:t(?:atic|ring)|witch) | t(?:hrow|r(?:ait|ue|y)) | u(?:nset|se) | var | while | xor | __(?:halt_compiler|(?:CLASS|DIR|F(?:ILE|UNCTION)|LINE|METHOD|NAMESPACE|TRAIT)__) )\b) [A-Za-z_\x7F-\xFF][\w\x7F-\xFF]* # valid character combination for identifiers ) (?'INTERFACE_LIST' \s+(?:\x5C|(?&VALID_ID))+ (?: \s*, \s*(?:\x5C|(?&VALID_ID))+ )* ) ) (?m-i) # ^ and $ match at line-breaks, case-sensitive ^\h* # optional leading white-space at start-of-line (?: (?:(?-i:abstract|final)\s+)? # optional class entry type (?-i:class)\s+ \K # discard text matched so far (?&VALID_ID) # identifier used as class name (?: # optional extends-from-class \s+(?-i:extends) \s+(?:\x5C|(?&VALID_ID))+ )? (?: # optional implements-class/interfaces \s+(?-i:implements) (?&INTERFACE_LIST) )? | (?-i:interface)\s+ \K # discard text matched so far (?&VALID_ID) # identifier used as interface name (?: # optional extends-from list \s+(?-i:extends) (?&INTERFACE_LIST) )? | (?-i:trait)\s+ \K # discard text matched so far (?&VALID_ID) # identifier used as trait name ) \s*\{ " openSymbole ="\{" closeSymbole="\}" > <className> <nameExpr expr="[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*" /> </className> <function mainExpr="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?m-i) # ^ and $ match at line-breaks, case-sensitive ^\h* # optional leading white-space at start-of-line (?:(?-i: # field modifiers p(?:r(?:ivate|otected)|ublic) # - access modifiers | abstract|final|static # - ... )\s+)* # require a white-space separator (?-i:function)\s+ \K # discard text matched so far (?:\x26\s*)? # optionally a reference (?'VALID_ID' # valid identifier, use as subroutine \b(?!(?-i: # keywords (case-sensitive), not to be used as identifier a(?:bstract|nd|rray|s) | b(?:ool|reak) | c(?:a(?:llable|se|tch)|l(?:ass|one)|on(?:st|tinue)) | d(?:e(?:clare|fault)|ie|o) | e(?:cho|lse(?:if)?|mpty|nd(?:declare|for(?:each)?|if|switch|while)|val|x(?:it|tends)) | f(?:alse|loat|inal|or(?:each)?|unction) | g(?:lobal|oto) | i(?:f|mplements|n(?:clude(?:_once)?|st(?:anceof|eadof)|t(?:erface)?)|sset) | list | mixed | n(?:amespace|ew|u(?:ll|meric)) | o(?:r|bject) | p(?:r(?:i(?:nt|vate)|otected)|ublic) | re(?:quire(?:_once)?|turn) | s(?:t(?:atic|ring)|witch) | t(?:hrow|r(?:ait|ue|y)) | u(?:nset|se) | var | while | xor | __(?:halt_compiler|(?:CLASS|DIR|F(?:ILE|UNCTION)|LINE|METHOD|NAMESPACE|TRAIT)__) )\b) [A-Za-z_\x7F-\xFF][\w\x7F-\xFF]* # valid character combination for identifiers ) # identifier used as method name \s*\( # start of function parameters (?:[^{;]*(?:\{|;)) # start of function body or abstract function without body " > <functionName> <funcNameExpr expr="(?:\x26\s*)?[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*\s*\((?:[^/{]|/(?![*/]))*" /> <!-- comment out the following node to display the method with parameters --> <funcNameExpr expr="(?:\x26\s*)?[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*" /> </functionName> </function> </classRange> <function mainExpr="(?x) # free-spacing (see `RegEx - Pattern Modifiers`) (?m-i) # ^ and $ match at line-breaks, case-sensitive ^\h* # optional leading white-space at start-of-line (?-i:function)\s+ \K # discard text matched so far (?:\x26\s*)? # optionally a reference (?'VALID_ID' # valid identifier, use as subroutine \b(?!(?-i: # keywords (case-sensitive), not to be used as identifier a(?:bstract|nd|rray|s) | b(?:ool|reak) | c(?:a(?:llable|se|tch)|l(?:ass|one)|on(?:st|tinue)) | d(?:e(?:clare|fault)|ie|o) | e(?:cho|lse(?:if)?|mpty|nd(?:declare|for(?:each)?|if|switch|while)|val|x(?:it|tends)) | f(?:alse|loat|inal|or(?:each)?|unction) | g(?:lobal|oto) | i(?:f|mplements|n(?:clude(?:_once)?|st(?:anceof|eadof)|t(?:erface)?)|sset) | list | mixed | n(?:amespace|ew|u(?:ll|meric)) | o(?:r|bject) | p(?:r(?:i(?:nt|vate)|otected)|ublic) | re(?:quire(?:_once)?|turn) | s(?:t(?:atic|ring)|witch) | t(?:hrow|r(?:ait|ue|y)) | u(?:nset|se) | var | while | xor | __(?:halt_compiler|(?:CLASS|DIR|F(?:ILE|UNCTION)|LINE|METHOD|NAMESPACE|TRAIT)__) )\b) [A-Za-z_\x7F-\xFF][\w\x7F-\xFF]* # valid character combination for identifiers ) # identifier used as function name \s*\( # start of function parameters [^{]*\{ # start of function body " > <functionName> <nameExpr expr="(?:\x26\s*)?[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*\s*\((?:[^/{]|/(?![*/]))*" /> <!-- comment out the following node to display the function with its parameters --> <!-- <nameExpr expr="(?:\x26\s*)?[A-Za-z_\x7F-\xFF][\w\x7F-\xFF]*" /> --> </functionName> </function> </parser>
-
I join GitHub, but I not sure of what I did for submit this piece of code.
https://github.com/TutoInformatik/notepad-plus-plus/pulls?q=is%3Apr+is%3Aclosed