branch: externals/phpinspect
commit ea90a008876d6650a227ee2f7ed7804389380368
Author: Hugo Thunnissen <de...@hugot.nl>
Commit: Hugo Thunnissen <de...@hugot.nl>

    Don't reuse unexpected keywords
---
 phpinspect-parser.el           | 50 ++++++++++++++++++++++++++++++------------
 phpinspect-token-predicates.el |  3 +++
 test/test-buffer-parsing.el    |  3 +--
 3 files changed, 40 insertions(+), 16 deletions(-)

diff --git a/phpinspect-parser.el b/phpinspect-parser.el
index 97a8665fb6..f18e652dba 100644
--- a/phpinspect-parser.el
+++ b/phpinspect-parser.el
@@ -392,7 +392,7 @@ root token, in string form without \":\" prefix.")
                       assignment-operator whitespace scope-keyword
                       static-keyword const-keyword use-keyword
                       class-keyword interface-keyword trait-keyword 
enum-keyword
-                      function-keyword word terminator here-doc string
+                      function-keyword unexpected-keyword-in-function-body 
word terminator here-doc string
                       string-concatenator comment block)
               :type list
               :read-only t
@@ -513,25 +513,35 @@ parsing incrementally."
         (catch 'phpinspect--continue
           (let ((parser (symbol-value name))
                 body)
+            ;; Check if parser has properties required to dynamically generate 
a
+            ;; predicate case.
             (unless (or (and (phpinspect-parser-delimiter-condition parser)
                              (phpinspect-parser-delimiter-predicate parser))
                         (and (phpinspect-parser-delimiter-predicate parser)
                              (phpinspect-parser-recycle-only-delimited 
parser)))
               (throw 'phpinspect--continue nil))
 
+            ;; When the last subtoken of the token matches the delimiter
+            ;; predicate, the token is "complete" and eligible for re-use
             (setq body `(,(phpinspect-parser-delimiter-predicate parser) (car 
(last ,token-sym))))
 
+            ;; If the parser has a delimiter condition, it must be matched
+            ;; before checking the delimiter predicate.
             (when-let ((condition (phpinspect-parser-delimiter-condition 
parser)))
               (setq body `(if (,(phpinspect-parser-delimiter-condition parser) 
,token-sym)
                               ,body
                             ,(not (phpinspect-parser-recycle-only-delimited 
parser)))))
 
+            ;; Only tokens that (could) have been parsed by this parser should
+            ;; be subjected to these conditions, so the `cond' condition must
+            ;; match the tokens lisp keyword with the tree keyword of the 
parser.
             (push `((eq (car ,token-sym) ,(intern (concat ":" 
(phpinspect-parser-tree-keyword parser))))
                     ,body)
                   cases))))
 
       `(defun ,predicate-name (,token-sym)
-         (cond ,@cases)))))
+         (and (not (phpinspect-token-unexpected-p ,token-sym))
+              (cond ,@cases))))))
 
 (eval-and-compile
   (defun phpinspect--get-parser-function-syms ()
@@ -573,6 +583,12 @@ parsing incrementally."
    (inline . t))
   (inline-quote (phpinspect-munch-token-without-attribs ,comma :comma)))
 
+(phpinspect-defhandler unexpected-keyword-in-function-body (word &rest 
_ignored)
+  "Handler for keywords that are valid in some cases, but not in function 
bodies."
+  ((regexp . "public\\|private\\|protected\\|readonly")
+   (inline . t))
+  (inline-quote (phpinspect-munch-token-without-attribs ,word 
:unexpected-keyword)))
+
 (phpinspect-defhandler word (word &rest _ignored)
   "Handler for bareword tokens"
   ((regexp . "[A-Za-z_\\][\\A-Za-z_0-9]*")
@@ -601,7 +617,7 @@ parsing incrementally."
   :tree-keyword "list"
   :handlers '(array tag equals list comma
                     attribute-reference static-attribute-reference variable 
assignment-operator
-                    whitespace function-keyword word terminator here-doc
+                    whitespace function-keyword 
unexpected-keyword-in-function-body word terminator here-doc
                     string string-concatenator comment block-without-scopes))
 
 (phpinspect-defhandler list (start-token max-point)
@@ -871,7 +887,7 @@ To parse trait use statements in class bodies, see
 (phpinspect-defparser const
   :tree-keyword "const"
   :recycle-only-delimited t
-  :handlers '(word comment assignment-operator string string-concatenator 
array terminator)
+  :handlers '(unexpected-keyword-in-function-body word comment 
assignment-operator string string-concatenator array terminator)
   :delimiter-predicate #'phpinspect-end-of-token-p)
 
 (phpinspect-defhandler const-keyword (start-token max-point)
@@ -895,7 +911,7 @@ To parse trait use statements in class bodies, see
   :tree-keyword "block"
   :handlers '(array tag equals string-concatenator list comma 
attribute-reference
                     static-attribute-reference variable
-                    assignment-operator whitespace function-keyword word
+                    assignment-operator whitespace function-keyword 
unexpected-keyword-in-function-body word
                     terminator here-doc string comment block-without-scopes))
 
 (phpinspect-defhandler block-without-scopes (start-token max-point)
@@ -1005,11 +1021,12 @@ Returns the consumed text string without face 
properties."
 
 (phpinspect-defparser class-declaration
   :tree-keyword "class-declaration"
-  :handlers '(comment extends-keyword implements-keyword comma word list 
terminator tag))
+  :handlers '(comment extends-keyword implements-keyword comma
+              unexpected-keyword-in-function-body word list terminator tag))
 
 (phpinspect-defparser declaration
   :tree-keyword "declaration"
-  :handlers '(comment word list terminator tag)
+  :handlers '(comment unexpected-keyword-in-function-body word list terminator 
tag)
   :recycle-only-delimited t
   :delimiter-predicate #'phpinspect-end-of-token-p)
 
@@ -1032,7 +1049,8 @@ Returns the consumed text string without face properties."
 
 (phpinspect-defparser scope-public
   :tree-keyword "public"
-  :handlers '(function-keyword static-keyword const-keyword class-variable 
here-doc
+  :handlers '(function-keyword unexpected-keyword-in-function-body
+                               static-keyword const-keyword class-variable 
here-doc
                                string string-concatenator terminator tag 
comment
                                assignment-operator array word)
   :recycle-only-delimited t
@@ -1040,7 +1058,8 @@ Returns the consumed text string without face properties."
 
 (phpinspect-defparser scope-private
   :tree-keyword "private"
-  :handlers '(function-keyword static-keyword const-keyword class-variable 
here-doc
+  :handlers '(function-keyword unexpected-keyword-in-function-body
+                               static-keyword const-keyword class-variable 
here-doc
                                string string-concatenator terminator tag 
comment
                                assignment-operator array word)
   :recycle-only-delimited t
@@ -1049,7 +1068,8 @@ Returns the consumed text string without face properties."
 (phpinspect-defparser scope-protected
   :tree-keyword "protected"
   :recycle-only-delimited t
-  :handlers '(function-keyword static-keyword const-keyword class-variable 
here-doc
+  :handlers '(function-keyword unexpected-keyword-in-function-body
+                               static-keyword const-keyword class-variable 
here-doc
                                string string-concatenator terminator tag 
comment
                                assignment-operator array word)
   :delimiter-predicate #'phpinspect--scope-terminator-p)
@@ -1069,7 +1089,7 @@ Returns the consumed text string without face properties."
 (phpinspect-defparser static
   :tree-keyword "static"
   :recycle-only-delimited t
-  :handlers '(comment function-keyword class-variable array word terminator 
tag)
+  :handlers '(comment function-keyword class-variable array 
unexpected-keyword-in-function-body word terminator tag)
   :delimiter-predicate #'phpinspect--static-terminator-p)
 
 (phpinspect-defhandler static-keyword (start-token max-point)
@@ -1088,8 +1108,9 @@ Returns the consumed text string without face properties."
 
 (phpinspect-defparser array
   :tree-keyword "array"
-  :handlers '(comment comma list here-doc string array variable
-                      attribute-reference static-attribute-reference word 
fat-arrow))
+  :handlers '(comment comma list here-doc string array variable 
attribute-reference
+                      static-attribute-reference 
unexpected-keyword-in-function-body
+                      word fat-arrow))
 
 (phpinspect-defhandler array (start-token max-point)
   "Handler for arrays, in the bracketet as well as the list notation"
@@ -1210,7 +1231,8 @@ the properties of the class"
                         assignment-operator whitespace scope-keyword
                         static-keyword const-keyword use-keyword class-keyword
                         interface-keyword trait-keyword enum-keyword
-                        function-keyword word terminator here-doc string 
string-concatenator
+                        function-keyword unexpected-keyword-in-function-body
+                        word terminator here-doc string string-concatenator
                         comment tag block))
 
 (defun phpinspect-parse-current-buffer ()
diff --git a/phpinspect-token-predicates.el b/phpinspect-token-predicates.el
index 339d476e2f..506486b6bf 100644
--- a/phpinspect-token-predicates.el
+++ b/phpinspect-token-predicates.el
@@ -404,4 +404,7 @@ Type can be any of the token types returned by
          ;; terminator = incomplete.
          (not (or block terminator))))))
 
+(define-inline phpinspect-token-unexpected-p (token)
+  (inline-quote (phpinspect-token-type-p ,token :unexpected-keyword)))
+
 (provide 'phpinspect-token-predicates)
diff --git a/test/test-buffer-parsing.el b/test/test-buffer-parsing.el
index 3af3ed1457..ef20b62c34 100644
--- a/test/test-buffer-parsing.el
+++ b/test/test-buffer-parsing.el
@@ -38,8 +38,7 @@
         return $foo()->bar->baz;
     }
 
-    // FIXME: Make this test succeed with \"public\" uncommented
-    /* public */ function fooBar(RealTime $rt) {
+    public function fooBar(RealTime $rt) {
         // stuff
     }
 }")

Reply via email to