diff --git a/CHANGELOG.md b/CHANGELOG.md index 95437a0..680a194 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,11 @@ # Next +Features: + +- Add the command `ede-php-autoload-reload-autoloads` to refresh the + composer autoloads when the composer configuration changed + +Fixes: + - Always load the root project when visiting a third-party source -- Improve ecukes tests +- Improve ecukes tests reliability diff --git a/README.org b/README.org index 2376a47..497d165 100644 --- a/README.org +++ b/README.org @@ -49,6 +49,12 @@ (add-hook 'php-mode-hook #'ede-php-autoload-mode) #+END_SRC +* Commands + + | Name | Description | + |-----------------------------------------+----------------------------------------------------------------| + | ~M-x ede-php-autoload-reload-autoloads~ | Similar to the reindexation in IDEs. Use it when your composer configuration changed to reload the autoloads. | + * License This project is released under the GPL v3 license. See =GPL= for details. diff --git a/ede-php-autoload.el b/ede-php-autoload.el index 983e348..d37e2f0 100644 --- a/ede-php-autoload.el +++ b/ede-php-autoload.el @@ -115,6 +115,16 @@ intended to be a subproject, so this argument is ignored." :safe-p t) 'unique)) +(defun ede-php-autoload-reload-autoloads () + "Reload the autoloads for the current projects. + +This has the same goal than a reindexation in IDEs. Use this +method when your composer.json file changed, or your vendor +directory has been updated in order to take the new autoloads +into account." + (interactive) + (ede-php-autoload-reload-autoloads-for-project (ede-current-project))) + ;;;; ;;;; Class loaders ;;;; @@ -147,8 +157,7 @@ to the associated directories." ;;;###autoload (defclass ede-php-autoload-project (ede-project eieio-instance-tracker) ((tracking-symbol :initform 'ede-php-autoload-project-list) - (class-loader :initarg :class-loader - :type ede-php-autoload-class-loader + (class-loader :type ede-php-autoload-class-loader :documentation "The project's class loader.") (include-path :initarg :include-path :type list @@ -157,21 +166,21 @@ to the associated directories." (system-include-path :initarg :system-include-path :type list :initform () - :documentation "The list of PHP include paths defined for the system."))) + :documentation "The list of PHP include paths defined for the system.") + (explicit-class-autoloads :initarg :explicit-class-autoloads + :type list + :documentation "The class autoloads explicitly defined at initialization"))) (defmethod initialize-instance ((this ede-php-autoload-project) &rest fields) "Make sure the :file is fully expanded." - (let ((class-autoloads (plist-get (car fields) :class-autoloads))) + (call-next-method this (list + :file (plist-get (car fields) :file) + :explicit-class-autoloads (plist-get (car fields) :class-autoloads) + :include-path (plist-get (car fields) :include-path) + :system-include-path (plist-get (car fields) :system-include-path))) - (setq class-autoloads (ede-php-autoload--append-composer-autoload-data - (file-name-directory (plist-get (car fields) :file)) - class-autoloads)) + (ede-php-autoload-reload-autoloads-for-project this) - (call-next-method this (list - :file (plist-get (car fields) :file) - :class-loader (ede-php-autoload-create-class-loader class-autoloads) - :include-path (plist-get (car fields) :include-path) - :system-include-path (plist-get (car fields) :system-include-path)))) (let ((f (expand-file-name (oref this file)))) ;; Remove any previous entries from the main list. (let ((old (eieio-instance-tracker-find (file-name-directory f) @@ -191,6 +200,18 @@ to the associated directories." (unless (slot-boundp this 'targets) (oset this :targets nil)))) +(defmethod ede-php-autoload-reload-autoloads-for-project ((this ede-php-autoload-project)) + "Regenerate the class loaders. + +This can be used when some composer dependencies changed, to take +the new autoloads into account." + (oset this class-loader + (ede-php-autoload-create-class-loader + (ede-php-autoload--append-composer-autoload-data + (file-name-directory (ede-project-root-directory this)) + (oref this explicit-class-autoloads)) + ))) + (defmethod ede-find-subproject-for-directory ((proj ede-php-autoload-project) dir) "Return PROJ, for handling all subdirs below DIR." proj) diff --git a/features/ede-php-autoload-composer.feature b/features/ede-php-autoload-composer.feature index 7c0df06..c276a8a 100644 --- a/features/ede-php-autoload-composer.feature +++ b/features/ede-php-autoload-composer.feature @@ -50,3 +50,10 @@ Feature: Composer EDE project creation Scenario: Visit a vendor file Given I visit "vendor/third-party/third-party/src/ThirdClass.php" in project "with-composer" Then the class "Psr0Ns_TheClass" should be detected in "src/Psr0Ns/TheClass.php" + + Scenario: Update the autoloads + Given I visit "src/main.php" in project "with-composer" + Then the class "NewNs\MyClass" should not be detected + Given I update the composer file + And I refresh the project autoloads + Then the class "NewNs\MyClass" should be detected in "src/NewNs/MyClass.php" diff --git a/features/step-definitions/ede-php-autoload-steps.el b/features/step-definitions/ede-php-autoload-steps.el index fcdea37..b135185 100644 --- a/features/step-definitions/ede-php-autoload-steps.el +++ b/features/step-definitions/ede-php-autoload-steps.el @@ -3,6 +3,14 @@ (find-file (ede-php-autoload-test-get-project-file-path file-path project-name)) )) +(Given "^I update the composer file" + (lambda () + (ede-php-autoload-test-set-composer "new"))) + +(Given "^I refresh the project autoloads" + (lambda () + (call-interactively #'ede-php-autoload-reload-autoloads))) + (Then "^ede-php-autoload-project should exist$" (lambda () (should (ede-php-autoload-project-p (ede-current-project))))) diff --git a/features/support/env.el b/features/support/env.el index abca8c3..99bef2b 100644 --- a/features/support/env.el +++ b/features/support/env.el @@ -28,6 +28,19 @@ (or (buffer-file-name) default-directory) ede-php-autoload-test-projects-root-path)))) +(defun ede-php-autoload-test-set-composer (composer-file-name) + "Set the composer file of the project with-composer. + +COMPOSER-FILE-NAME is either default or new." + (let* ((project-root (f-join ede-php-autoload-test-projects-root-path "with-composer")) + (destination (f-join project-root "composer.json"))) + + (when (f-exists? destination) + (f-delete destination)) + + (f-copy (f-join project-root (format "%s-composer.json" composer-file-name)) + destination))) + (add-to-list 'load-path ede-php-autoload-root-path) (package-generate-autoloads "ede-php-autoload" ede-php-autoload-root-path) @@ -38,6 +51,9 @@ (Before (setq ede-projects nil) + + (ede-php-autoload-test-set-composer "default") + ;; Define projects ;; The composer projet is auto-detected (ede-php-autoload-project "Without composer" diff --git a/test/projects/with-composer/default-composer.json b/test/projects/with-composer/default-composer.json new file mode 100644 index 0000000..a6aff70 --- /dev/null +++ b/test/projects/with-composer/default-composer.json @@ -0,0 +1,25 @@ +{ + "autoload": { + "psr-0": { + "Psr0Ns": "src/", + "": "src/Fallback/Psr0" + }, + "psr-4": { + "Psr4Ns": "src/Psr4Ns", + "MultiDirNs": ["src/MultiDirNs1", "src/MultiDirNs2"], + "": "src/Fallback/Psr4" + } + }, + "autoload-dev": { + "psr-4": { + "AutoloadDev": "src/AutoloadDev" + } + }, + "require": { + "third-party/third-party": "*", + "target-dir/target-dir": "*" + }, + "require-dev": { + "third-party/dev-dependency": "*" + } +} diff --git a/test/projects/with-composer/new-composer.json b/test/projects/with-composer/new-composer.json new file mode 100644 index 0000000..f5cb5a9 --- /dev/null +++ b/test/projects/with-composer/new-composer.json @@ -0,0 +1,7 @@ +{ + "autoload": { + "psr-4": { + "NewNs": "src/NewNs" + } + } +} diff --git a/test/projects/with-composer/src/NewNs/MyClass.php b/test/projects/with-composer/src/NewNs/MyClass.php new file mode 100644 index 0000000..311b7be --- /dev/null +++ b/test/projects/with-composer/src/NewNs/MyClass.php @@ -0,0 +1,7 @@ +