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

    Implement initial algorithm for indexation of traits
    
    This just add a function, it is not in use for anything yet
---
 phpinspect-index.el            | 59 ++++++++++++++++++++++++++++++++++++++++++
 phpinspect-parser.el           |  2 +-
 phpinspect-token-predicates.el |  5 +++-
 test/test-index.el             | 14 ++++++++++
 test/test-parser.el            | 13 ++++++++++
 5 files changed, 91 insertions(+), 2 deletions(-)

diff --git a/phpinspect-index.el b/phpinspect-index.el
index ffa0689d82..12b226241b 100644
--- a/phpinspect-index.el
+++ b/phpinspect-index.el
@@ -707,5 +707,64 @@ Returns a list of type name strings."
   "Index a PHP file for classes and the methods they have"
   (phpinspect--index-tokens (phpinspect-parse-current-buffer)))
 
+
+(defun phpinspect--index-trait-use (token type-resolver add-used-types)
+  (cl-assert (phpinspect-use-p token))
+  (setq token (cddr (seq-filter #'phpinspect-not-comment-p token)))
+
+  (let ((block? (car (last token)))
+        used-types config match)
+    (when (phpinspect-end-of-statement-p block?)
+      (setq token (butlast token)))
+
+    (setq token (seq-filter #'phpinspect-not-comma-p token))
+
+    (dolist (word token)
+      (when (phpinspect-word-p word)
+        (push (cadr token) used-types)
+        (push `(,(funcall type-resolver (phpinspect--make-type :name (cadr 
word))))
+              config)))
+
+    (when (phpinspect-block-p block?)
+      (setq block? (cdr (seq-filter #'phpinspect-not-comment-p block?)))
+
+      (while block?
+        (cond ((phpinspect-comma-p (car block?))
+               (pop block?))
+              ;; Override
+              ((phpinspect--match-sequence block?
+                 :f #'phpinspect-word-p
+                 :f #'phpinspect-static-attrib-p
+                 :m '(:word "insteadof")
+                 :f #'phpinspect-word-p
+                 :rest *)
+               (let* ((type (funcall type-resolver (phpinspect--make-type 
:name (cadr (nth 3 block?)))))
+                      (t-config (assoc type config #'phpinspect--type=)))
+                 (when t-config
+                   (push `(override ,(cadadr (cadr block?))
+                                    ,(funcall type-resolver
+                                              (phpinspect--make-type :name 
(cadar block?))))
+                         (cdr t-config))))
+
+               (setq block? (nthcdr 4 block?)))
+
+              ;; alias
+              ((phpinspect--match-sequence block?
+                 :f #'phpinspect-word-p
+                 :f #'phpinspect-static-attrib-p
+                 :m '(:word "as")
+                 :f #'phpinspect-word-p
+                 :rest *)
+               (let* ((type (funcall type-resolver (phpinspect--make-type 
:name (cadar block?))))
+                      (t-config (assoc type config #'phpinspect--type=)))
+
+                 (when t-config
+                   (push `(alias ,(cadadr (cadr block?)) ,(cadr (nth 3 
block?)))
+                         (cdr t-config))))
+
+               (setq block? (nthcdr 4 block?)))))
+
+      config)))
+
 (provide 'phpinspect-index)
 ;;; phpinspect-index.el ends here
diff --git a/phpinspect-parser.el b/phpinspect-parser.el
index 948fc38470..d5c7a96d0f 100644
--- a/phpinspect-parser.el
+++ b/phpinspect-parser.el
@@ -599,7 +599,7 @@ nature like argument lists"
 
 (phpinspect-defparser use
   :tree-keyword "use"
-  :handlers '(word tag block-without-scopes terminator)
+  :handlers '(comment word tag block-without-scopes comma terminator)
   :delimiter-predicate #'phpinspect-end-of-use-p)
 
 (phpinspect-defhandler use-keyword (start-token max-point)
diff --git a/phpinspect-token-predicates.el b/phpinspect-token-predicates.el
index 76acb8425c..29690f0bcc 100644
--- a/phpinspect-token-predicates.el
+++ b/phpinspect-token-predicates.el
@@ -51,6 +51,9 @@ Type can be any of the token types returned by
 (defun phpinspect-comma-p (token)
   (phpinspect-token-type-p token :comma))
 
+(defun phpinspect-not-comma-p (token)
+  (not (phpinspect-comma-p token)))
+
 (defsubst phpinspect-terminator-p (token)
   (phpinspect-token-type-p token :terminator))
 
@@ -72,7 +75,7 @@ Type can be any of the token types returned by
 
 (defun phpinspect-end-of-use-p (token)
   (or (phpinspect-block-p token)
-      (phpinspect-end-of-token-p token)))
+      (phpinspect-terminator-p token)))
 
 (defun phpinspect-static-p (token)
   (phpinspect-token-type-p token :static))
diff --git a/test/test-index.el b/test/test-index.el
index 718ffeb2ef..9244fef669 100644
--- a/test/test-index.el
+++ b/test/test-index.el
@@ -439,3 +439,17 @@ if (something()) {
             (conditional (cadr functions)))
         (should (string= "conditional" (phpinspect--function-name 
conditional)))
         (should (string= "nestedConditional" (phpinspect--function-name 
nestedConditional)))))))
+
+(ert-deftest phpinspect-index-trait-use ()
+  (let* ((tree (with-temp-buffer
+                 (insert "use B, C { C::foo insteadof B, B::bar as banana }")
+                 (goto-char (point-min))
+                 (phpinspect--parse-use (current-buffer) (point-max))))
+         (expected `((,(phpinspect--make-type :name "\\C" :fully-qualified t))
+                     (,(phpinspect--make-type :name "\\B" :fully-qualified t)
+                      (alias "bar" "banana")
+                      (override "foo" ,(phpinspect--make-type :name "\\C" 
:fully-qualified t)))))
+         (index (phpinspect--index-trait-use tree 
(phpinspect--make-type-resolver nil nil nil) nil)))
+
+    (should index)
+    (should (equal expected index))))
diff --git a/test/test-parser.el b/test/test-parser.el
index 0e86853e83..6df6e53fab 100644
--- a/test/test-parser.el
+++ b/test/test-parser.el
@@ -144,3 +144,16 @@ class TestClass {
         (expected-result (phpinspect--index-tokens
                           (phpinspect-test-read-fixture-data "IndexClass1"))))
     (should (equal index expected-result))))
+
+(ert-deftest phpinspect-parse-class-with-trait-uses ()
+  (let ((tree (phpinspect-parse-string "class A { use B, C { C::foo insteadof 
A } }")))
+
+    (should tree)
+    (should (equal
+             '(:root (:class (:declaration (:word "class") (:word "A"))
+                             (:block
+                              (:use (:word "B") (:comma ",") (:word "C")
+                                    (:block
+                                     (:word "C") (:static-attrib (:word "foo"))
+                                     (:word "insteadof") (:word "A"))))))
+            tree))))

Reply via email to