From ef9a7336cf18f466d2a6629040e55cf957c03443 Mon Sep 17 00:00:00 2001 From: Hugo Thunnissen Date: Wed, 29 Jun 2022 12:29:36 +0200 Subject: [PATCH] Replace virtual-directory with more general virtual-fs implementation --- phpinspect-autoload.el | 94 ++++++++++------------------------------- phpinspect-fs.el | 86 +++++++++++++++++++++++++++++++++++++ test/phpinspect-test.el | 1 + test/test-autoload.el | 42 +++++++++--------- test/test-fs.el | 88 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 219 insertions(+), 92 deletions(-) create mode 100644 phpinspect-fs.el create mode 100644 test/test-fs.el diff --git a/phpinspect-autoload.el b/phpinspect-autoload.el index c5721cd..98e83d3 100644 --- a/phpinspect-autoload.el +++ b/phpinspect-autoload.el @@ -24,73 +24,23 @@ ;;; Code: (require 'cl-lib) +(require 'phpinspect-project) +(require 'phpinspect-fs) (cl-defstruct (phpinspect-autoloader (:constructor phpinspect-make-autoloader)) - (types (make-hash-table :test 'eq) + (project nil + :type phpinspect--project + :documentation "The project that this autoloader can find files for") + (own-types (make-hash-table :test 'eq :size 10000 :rehash-size 10000) + :type hash-table + :documentation "The internal types that can be + autoloaded through this autoloader") + (types (make-hash-table :test 'eq :size 10000 :rehash-size 10000) :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)))) + "The external types that can be autoloaded through this autoloader.")) + (cl-defstruct (phpinspect-psr0 (:constructor phpinspect-make-psr0-generated)) @@ -127,25 +77,25 @@ (phpinspect-intern-name (concat "\\" (or prefix "") - (replace-regexp-in-string "/" - "\\\\" - (string-remove-suffix - ".php" - (string-remove-prefix - (phpinspect-directory-get-location dir) - filename)))))) + (replace-regexp-in-string + "/" "\\\\" + (string-remove-suffix + ".php" + (string-remove-prefix dir filename)))))) (cl-defmethod phpinspect-al-strategy-fill-typehash ((strategy phpinspect-psr0) - typehash) + fs + typehash) (dolist (dir (phpinspect-psr0-directories strategy)) - (dolist (file (phpinspect-directory-list-files dir)) + (dolist (file (phpinspect-fs-directory-files-recursively fs dir "\\.php$")) (puthash (phpinspect-filename-to-typename dir file) file typehash)))) (cl-defmethod phpinspect-al-strategy-fill-typehash ((strategy phpinspect-psr4) + fs typehash) (let ((prefix (phpinspect-psr4-prefix strategy))) (dolist (dir (phpinspect-psr4-directories strategy)) - (dolist (file (phpinspect-directory-list-files dir)) + (dolist (file (phpinspect-fs-directory-files-recursively fs dir "\\.php$")) (puthash (phpinspect-filename-to-typename dir file prefix) file typehash))))) (provide 'phpinspect-autoload) diff --git a/phpinspect-fs.el b/phpinspect-fs.el new file mode 100644 index 0000000..e84b155 --- /dev/null +++ b/phpinspect-fs.el @@ -0,0 +1,86 @@ +;;; phpinspect-fs.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: + +(cl-defstruct (phpinspect-fs (:constructor phpinspect-make-fs))) + +(cl-defstruct (phpinspect-virtual-fs (:constructor phpinspect-make-virtual-fs)) + (files (make-hash-table :test 'equal) + :type hash-table + :documentation + "The files in the virtual filesystem")) + +(cl-defgeneric phpinspect-fs-file-exists-p (fs file)) +(cl-defgeneric phpinspect-fs-insert-file-contents (fs file)) +(cl-defgeneric phpinspect-fs-directory-files (fs directory match)) +(cl-defgeneric phpinspect-fs-directory-files-recursively (fs directory match)) + +(cl-defmethod phpinspect-fs-file-exists-p ((fs phpinspect-fs) file) + (file-exists-p file)) + +(cl-defmethod phpinspect-fs-file-exists-p ((fs phpinspect-virtual-fs) file) + (and (gethash file (phpinspect-virtual-fs-files fs)) t)) + +(cl-defmethod phpinspect-fs-insert-file-contents ((fs phpinspect-fs) file) + (insert-file-contents-literally file)) + +(cl-defmethod phpinspect-fs-insert-file-contents ((fs phpinspect-virtual-fs) file) + (insert (or (gethash file (phpinspect-virtual-fs-files fs)) ""))) + +(cl-defmethod phpinspect-fs-directory-files ((fs phpinspect-fs) directory &optional match) + (directory-files directory t match t)) + +(cl-defmethod phpinspect-fs-directory-files ((fs phpinspect-virtual-fs) directory &optional match) + (setq directory (replace-regexp-in-string "[/]+" "/" (concat directory "/"))) + (let ((files)) + (maphash + (lambda (file _ignored) + (let ((basename (string-remove-prefix directory file))) + (when (and (string-prefix-p directory file) + (string-match-p "^[^/]*$" basename) + (if match (string-match-p match basename) t)) + (push file files)))) + (phpinspect-virtual-fs-files fs)) + files)) + +(cl-defmethod phpinspect-fs-directory-files-recursively ((fs phpinspect-fs) directory &optional match) + (directory-files-recursively directory + match + t ;; Ignore directories that cannot be read + t ;; follow symlinks + )) + +(cl-defmethod phpinspect-fs-directory-files-recursively ((fs phpinspect-virtual-fs) directory &optional match) + (setq directory (replace-regexp-in-string "[/]+" "/" (concat directory "/"))) + (let ((files)) + (maphash + (lambda (file _ignored) + (when (and (string-prefix-p directory file) + (if match (string-match-p match file) t)) + (push file files))) + (phpinspect-virtual-fs-files fs)) + files)) + +(provide 'phpinspect-fs) +;;; phpinspect-fs.el ends here diff --git a/test/phpinspect-test.el b/test/phpinspect-test.el index e9fb7ef..4c4ba1c 100644 --- a/test/phpinspect-test.el +++ b/test/phpinspect-test.el @@ -499,6 +499,7 @@ class Thing (load-file (concat phpinspect-test-directory "/test-worker.el")) (load-file (concat phpinspect-test-directory "/test-autoload.el")) +(load-file (concat phpinspect-test-directory "/test-fs.el")) (provide 'phpinspect-test) ;;; phpinspect-test.el ends here diff --git a/test/test-autoload.el b/test/test-autoload.el index e38d41d..85df039 100644 --- a/test/test-autoload.el +++ b/test/test-autoload.el @@ -25,35 +25,36 @@ (require 'ert) +(require 'phpinspect-fs) (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/")) + (let* ((fs (phpinspect-make-virtual-fs)) (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)) + (phpinspect-virtual-fs-files fs)) (puthash "/home/user/projects/app/src/Kernel.php" "" - (phpinspect-virtual-directory-files directory1)) + (phpinspect-virtual-fs-files fs)) (puthash "/home/user/projects/app/src/App/Controller/Banana.php" "" - (phpinspect-virtual-directory-files directory1)) + (phpinspect-virtual-fs-files fs)) (puthash "/home/user/projects/app/lib/Mailer_Lib.php" "" - (phpinspect-virtual-directory-files directory2)) + (phpinspect-virtual-fs-files fs)) - (setf (phpinspect-psr0-directories autoload) (list directory1 directory2)) + (setf (phpinspect-psr0-directories autoload) (list "/home/user/projects/app/src/" + "/home/user/projects/app/lib/")) - (phpinspect-al-strategy-fill-typehash autoload typehash) + (phpinspect-al-strategy-fill-typehash autoload fs typehash) + + (should-not (hash-table-empty-p typehash)) (should (string= "/home/user/projects/app/src/App/Services/SuperService.php" (gethash (phpinspect-intern-name "\\App\\Services\\SuperService") @@ -70,32 +71,33 @@ 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/")) + (let* ((fs (phpinspect-make-virtual-fs)) (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)) + (phpinspect-virtual-fs-files fs)) (puthash "/home/user/projects/app/src/Kernel.php" "" - (phpinspect-virtual-directory-files directory1)) + (phpinspect-virtual-fs-files fs)) + (puthash "/home/user/projects/app/src/Controller/Banana.php" "" - (phpinspect-virtual-directory-files directory1)) + (phpinspect-virtual-fs-files fs)) (puthash "/home/user/projects/app/lib/Mailer_Lib.php" "" - (phpinspect-virtual-directory-files directory2)) + (phpinspect-virtual-fs-files fs)) + + (setf (phpinspect-psr4-directories autoload) (list "/home/user/projects/app/src/" + "/home/user/projects/app/lib/")) - (setf (phpinspect-psr4-directories autoload) (list directory1 directory2)) + (phpinspect-al-strategy-fill-typehash autoload fs typehash) - (phpinspect-al-strategy-fill-typehash autoload typehash) + (should-not (hash-table-empty-p typehash)) (should (string= "/home/user/projects/app/src/Services/SuperService.php" (gethash (phpinspect-intern-name "\\App\\Services\\SuperService") diff --git a/test/test-fs.el b/test/test-fs.el new file mode 100644 index 0000000..c83ebfe --- /dev/null +++ b/test/test-fs.el @@ -0,0 +1,88 @@ +;;; 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 'phpinspect-fs) + +(ert-deftest phpinspect-virtual-fs-file-exists-p () + (let ((fs (phpinspect-make-virtual-fs))) + (puthash "/test/test.txt" "contents" (phpinspect-virtual-fs-files fs)) + + (should (phpinspect-fs-file-exists-p fs "/test/test.txt")))) + +(ert-deftest phpinspect-virtual-fs-insert-file-contents () + (let ((fs (phpinspect-make-virtual-fs))) + (puthash "/test/test.txt" "contents" (phpinspect-virtual-fs-files fs)) + + (with-temp-buffer + (phpinspect-fs-insert-file-contents fs "/test/test.txt") + (should (string= "contents" (buffer-string)))) + + (with-temp-buffer + (phpinspect-fs-insert-file-contents fs "/test/nonexistant") + (should (string= "" (buffer-string)))))) + +(ert-deftest phpinspect-virtual-fs-directory-files-and-recursively () + (let ((fs (phpinspect-make-virtual-fs))) + (puthash "/test/test.txt" "contents" (phpinspect-virtual-fs-files fs)) + (puthash "/a/b/c/dee.match" "contents" (phpinspect-virtual-fs-files fs)) + (puthash "/a/b/c/cee.match" "contents" (phpinspect-virtual-fs-files fs)) + (puthash "/a/b/c/aaa.match" "contents" (phpinspect-virtual-fs-files fs)) + (puthash "/a/b/c/nope.nomatch" "contents" (phpinspect-virtual-fs-files fs)) + (puthash "/a/b/d/jee.match" "contents" (phpinspect-virtual-fs-files fs)) + + (let ((files (phpinspect-fs-directory-files fs "/test/"))) + (should (equal '("/test/test.txt") files))) + + (let ((files (phpinspect-fs-directory-files fs "/a/b/c"))) + (should (member "/a/b/c/dee.match" files)) + (should (member "/a/b/c/cee.match" files)) + (should (member "/a/b/c/aaa.match" files)) + (should (member "/a/b/c/nope.nomatch" files))) + + (let ((files (phpinspect-fs-directory-files fs "/a/b/c" "\\.match$"))) + (should (member "/a/b/c/dee.match" files)) + (should (member "/a/b/c/cee.match" files)) + (should (member "/a/b/c/aaa.match" files)) + (should (not (member "/a/b/c/nope.nomatch" files)))) + + (let ((files (phpinspect-fs-directory-files-recursively fs "/a/b" "\\.match$"))) + (should (member "/a/b/c/dee.match" files)) + (should (member "/a/b/c/cee.match" files)) + (should (member "/a/b/c/aaa.match" files)) + (should (not (member "/a/b/c/nope.nomatch" files)))) + + (let ((files (phpinspect-fs-directory-files-recursively fs "/a/b"))) + (should (member "/a/b/c/dee.match" files)) + (should (member "/a/b/c/cee.match" files)) + (should (member "/a/b/c/aaa.match" files)) + (should (member "/a/b/c/nope.nomatch" files)) + (should (member "/a/b/d/jee.match" files))) + + (let ((files (phpinspect-fs-directory-files-recursively fs "/a/b" "\\.match$"))) + (should (member "/a/b/c/dee.match" files)) + (should (member "/a/b/c/cee.match" files)) + (should (member "/a/b/c/aaa.match" files)) + (should (not (member "/a/b/c/nope.nomatch" files))) + (should (member "/a/b/d/jee.match" files)))))