From 153ff71fcf4c035f336be0c759a110aba411ef0a Mon Sep 17 00:00:00 2001 From: Hugo Thunnissen Date: Mon, 27 Jun 2022 14:00:43 +0200 Subject: [PATCH] WIP: Implement psr0 and psr4 autoload strategies --- README.md | 2 +- phpinspect-autoload.el | 152 ++++++++++++++++++++++++++++++++++++++++ test/phpinspect-test.el | 1 + test/test-autoload.el | 112 +++++++++++++++++++++++++++++ 4 files changed, 266 insertions(+), 1 deletion(-) create mode 100644 phpinspect-autoload.el create mode 100644 test/test-autoload.el diff --git a/README.md b/README.md index fb0011d..cb50b05 100644 --- a/README.md +++ b/README.md @@ -45,5 +45,5 @@ Tests are implemented using `ert`. You can run them in batch mode with the follo command: ```bash -emacs -batch -l ert -l ./phpinspect.el -l ./test/phpinspect-test.el -f ert-run-tests-batch-and-exit +emacs -L ./ -batch -l ert -l ./phpinspect.el -l ./test/phpinspect-test.el -f ert-run-tests-batch-and-exit ``` diff --git a/phpinspect-autoload.el b/phpinspect-autoload.el new file mode 100644 index 0000000..c5721cd --- /dev/null +++ b/phpinspect-autoload.el @@ -0,0 +1,152 @@ +;;; phpinspect-autoload.el --- PHP parsing and completion package -*- lexical-binding: t; -*- + +;; Copyright (C) 2021 Free Software Foundation, Inc + +;; Author: Hugo Thunnissen +;; Keywords: php, languages, tools, convenience +;; Version: 0 + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;;; Code: + +(require 'cl-lib) + +(cl-defstruct (phpinspect-autoloader + (:constructor phpinspect-make-autoloader)) + (types (make-hash-table :test 'eq) + :type hash-table + :documentation + "The types that can be autoloaded through this autoloader.") + (strategies nil + :type list + :documentation + "The strategies that this autoloader can employ for its purpose.")) + +(cl-defstruct (phpinspect-directory + (:constructor phpinspect-make-directory)) + (location nil + :type string + :documentation + "The filepath to the directory")) + +(cl-defstruct (phpinspect-virtual-directory + (:constructor phpinspect-make-virtual-directory)) + (location nil + :type string + :documentation + "The filepath to the directory") + (files (make-hash-table :test 'equal) + :type hash-table + :documentation + "The files in the virtual directory")) + +(cl-defgeneric phpinspect-directory-list-files (directory) + "List all PHP files in DIRECTORY") + +(cl-defmethod phpinspect-directory-list-files ((dir phpinspect-directory)) + "List all PHP files in DIR." + (directory-files-recursively (phpinspect-directory-location dir) + ".*.php$" + t ;; Ignore directories that cannot be read + t ;; follow symlinks + )) + +(cl-defmethod phpinspect-directory-list-files ((dir phpinspect-virtual-directory)) + "List all virtual files that DIR contains." + (let ((files)) + (maphash (lambda (file _) + (push file files)) + (phpinspect-virtual-directory-files dir)) + files)) + +(cl-defgeneric phpinspect-directory-list-files (directory) + "List all PHP files in DIRECTORY") + +(cl-defmethod phpinspect-directory-get-location ((dir phpinspect-directory)) + "Get location of PHP dir." + (phpinspect-directory-location dir)) + +(cl-defmethod phpinspect-directory-get-location ((dir phpinspect-virtual-directory)) + "List all virtual files that DIR contains." + (phpinspect-virtual-directory-location dir)) + +(cl-defmethod phpinspect-directory-insert-file-contents ((dir phpinspect-directory) + (file string)) + (insert-file-contents file)) + +(cl-defmethod phpinspect-directory-insert-file-contents ((dir phpinspect-virtual-directory) + (file string)) + (insert (gethash file (phpinspect-virtual-directory-files dir)))) + +(cl-defstruct (phpinspect-psr0 + (:constructor phpinspect-make-psr0-generated)) + (prefix nil + :type string + :documentation "The namespace prefix for which the directories contain code.") + (directories nil + :type list + :documentation + "The directories that this autoloader finds code in.")) + +(cl-defstruct (phpinspect-psr4 + (:constructor phpinspect-make-psr4-generated)) + (prefix nil + :type string + :documentation "The namespace prefix for which the directories contain code.") + (directories nil + :type list + :documentation + "The directories that this autoloader finds code in.")) + +(cl-defstruct (phpinspect-classmap + (:constructor phpinspect-make-classmap-generated)) + (directories nil + :type list + :documentation + "The directories that this autoloader finds code in.")) + +(cl-defgeneric phpinspect-al-strategy-fill-typehash (strategy typehash) + "Make STRATEGY return a map with type names as keys and the + paths to the files they are defined in as values.") + +(defsubst phpinspect-filename-to-typename (dir filename &optional prefix) + (phpinspect-intern-name + (concat "\\" + (or prefix "") + (replace-regexp-in-string "/" + "\\\\" + (string-remove-suffix + ".php" + (string-remove-prefix + (phpinspect-directory-get-location dir) + filename)))))) + +(cl-defmethod phpinspect-al-strategy-fill-typehash ((strategy phpinspect-psr0) + typehash) + (dolist (dir (phpinspect-psr0-directories strategy)) + (dolist (file (phpinspect-directory-list-files dir)) + (puthash (phpinspect-filename-to-typename dir file) file typehash)))) + +(cl-defmethod phpinspect-al-strategy-fill-typehash ((strategy phpinspect-psr4) + typehash) + (let ((prefix (phpinspect-psr4-prefix strategy))) + (dolist (dir (phpinspect-psr4-directories strategy)) + (dolist (file (phpinspect-directory-list-files dir)) + (puthash (phpinspect-filename-to-typename dir file prefix) file typehash))))) + +(provide 'phpinspect-autoload) +;;; phpinspect-autoload.el ends here diff --git a/test/phpinspect-test.el b/test/phpinspect-test.el index 0774bb2..e9fb7ef 100644 --- a/test/phpinspect-test.el +++ b/test/phpinspect-test.el @@ -498,6 +498,7 @@ class Thing (phpinspect-parse-string php-code-bare)))))) (load-file (concat phpinspect-test-directory "/test-worker.el")) +(load-file (concat phpinspect-test-directory "/test-autoload.el")) (provide 'phpinspect-test) ;;; phpinspect-test.el ends here diff --git a/test/test-autoload.el b/test/test-autoload.el new file mode 100644 index 0000000..e38d41d --- /dev/null +++ b/test/test-autoload.el @@ -0,0 +1,112 @@ +;;; test-autoload.el --- Unit tests for phpinspect.el -*- lexical-binding: t; -*- + +;; Copyright (C) 2021 Free Software Foundation, Inc. + +;; Author: Hugo Thunnissen + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; + +;;; Code: + + +(require 'ert) +(require 'phpinspect-autoload) + +(ert-deftest phpinspect-psr0-fill-typehash () + (let* ((directory1 (phpinspect-make-virtual-directory + :location "/home/user/projects/app/src/")) + (directory2 (phpinspect-make-virtual-directory + :location "/home/user/projects/app/lib/")) + (typehash (make-hash-table :size 10 :test 'eq)) + (autoload + (phpinspect-make-psr0-generated :prefix "App\\"))) + + (puthash "/home/user/projects/app/src/App/Services/SuperService.php" + "" + (phpinspect-virtual-directory-files directory1)) + + (puthash "/home/user/projects/app/src/Kernel.php" + "" + (phpinspect-virtual-directory-files directory1)) + (puthash "/home/user/projects/app/src/App/Controller/Banana.php" + "" + (phpinspect-virtual-directory-files directory1)) + + (puthash "/home/user/projects/app/lib/Mailer_Lib.php" + "" + (phpinspect-virtual-directory-files directory2)) + + (setf (phpinspect-psr0-directories autoload) (list directory1 directory2)) + + (phpinspect-al-strategy-fill-typehash autoload typehash) + + (should (string= "/home/user/projects/app/src/App/Services/SuperService.php" + (gethash (phpinspect-intern-name "\\App\\Services\\SuperService") + typehash))) + (should (string= "/home/user/projects/app/src/Kernel.php" + (gethash (phpinspect-intern-name "\\Kernel") + typehash))) + (should (string= "/home/user/projects/app/src/App/Controller/Banana.php" + (gethash (phpinspect-intern-name "\\App\\Controller\\Banana") + typehash))) + + (should (string= "/home/user/projects/app/lib/Mailer_Lib.php" + (gethash (phpinspect-intern-name "\\Mailer_Lib") + typehash))))) + +(ert-deftest phpinspect-psr4-fill-typehash () + (let* ((directory1 (phpinspect-make-virtual-directory + :location "/home/user/projects/app/src/")) + (directory2 (phpinspect-make-virtual-directory + :location "/home/user/projects/app/lib/")) + (typehash (make-hash-table :size 10 :test 'eq)) + (autoload + (phpinspect-make-psr4-generated :prefix "App\\"))) + + (puthash "/home/user/projects/app/src/Services/SuperService.php" + "" + (phpinspect-virtual-directory-files directory1)) + + (puthash "/home/user/projects/app/src/Kernel.php" + "" + (phpinspect-virtual-directory-files directory1)) + (puthash "/home/user/projects/app/src/Controller/Banana.php" + "" + (phpinspect-virtual-directory-files directory1)) + + (puthash "/home/user/projects/app/lib/Mailer_Lib.php" + "" + (phpinspect-virtual-directory-files directory2)) + + (setf (phpinspect-psr4-directories autoload) (list directory1 directory2)) + + (phpinspect-al-strategy-fill-typehash autoload typehash) + + (should (string= "/home/user/projects/app/src/Services/SuperService.php" + (gethash (phpinspect-intern-name "\\App\\Services\\SuperService") + typehash))) + (should (string= "/home/user/projects/app/src/Kernel.php" + (gethash (phpinspect-intern-name "\\App\\Kernel") + typehash))) + (should (string= "/home/user/projects/app/src/Controller/Banana.php" + (gethash (phpinspect-intern-name "\\App\\Controller\\Banana") + typehash))) + + (should (string= "/home/user/projects/app/lib/Mailer_Lib.php" + (gethash (phpinspect-intern-name "\\App\\Mailer_Lib") + typehash)))))