diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 25d4be7d..4eb8d06e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,7 +37,7 @@ jobs: - uses: actions/checkout@v2 - name: Run tests if: matrix.allow_failure != true - run: 'make test' + run: 'make .cask test' - name: Run tests (allow failure) if: matrix.allow_failure == true run: 'make test || true' diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f2a6446..d7779fe4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,19 @@ All notable changes of the PHP Mode 1.19.1 release series are documented in this * Support new PHP 8.0 and 8.1 syntax hilighting and indentation * [8.0] `#[Attributes]` + * Add `php-imenu-generic-expression-default` for default value or `php-imenu-generic-expression` + * Add `php-imenu-generic-expression-legacy` for compatibility + * Add `php-imenu-generic-expression-simple` for simple display + +### Changed + + * Re-organized `php-imenu-generic-expression` + * Added `Import`, `Constants` and `Properties` + * Removed `Anonymous Functions` + * Renamed `Named Functions` to `Functions` + * Renamed `All Methods` to `Methods` + * Removed `Public Methods`, `Protected Methods` and `Provate Methods` + * Unified `Classes`, `Traits`, `Interfaces` into `Classes` ## [1.24.0] - 2021-03-07 diff --git a/Makefile b/Makefile index c495e2d6..e27eeca3 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,7 @@ dev: # # for an example of using a script like this with the 'git bisect run' # command. -test: .cask clean all +test: clean all touch tests/project/1/.git $(EMACS) -Q -batch -L lisp/ --eval \ "(let ((default-directory (expand-file-name \".cask\" default-directory))) \ diff --git a/lisp/php-mode.el b/lisp/php-mode.el index e35b688f..4a53a960 100644 --- a/lisp/php-mode.el +++ b/lisp/php-mode.el @@ -1195,7 +1195,9 @@ After setting the stylevars run hooks according to STYLENAME (add-hook 'syntax-propertize-extend-region-functions #'php-syntax-propertize-extend-region t t) - (setq imenu-generic-expression php-imenu-generic-expression) + (setq imenu-generic-expression (if (symbolp php-imenu-generic-expression) + (symbol-value php-imenu-generic-expression) + php-imenu-generic-expression)) ;; PHP vars are case-sensitive (setq case-fold-search t) diff --git a/lisp/php.el b/lisp/php.el index 3cc23cfe..0ae6d342 100644 --- a/lisp/php.el +++ b/lisp/php.el @@ -227,7 +227,7 @@ it is the character that will terminate the string, or t if the string should be "Regular expression for a PHP function.") (eval-when-compile - (defun php-create-regexp-for-method (&optional visibility) + (cl-defun php-create-regexp-for-method (&optional visibility &key include-args) "Make a regular expression for methods with the given VISIBILITY. VISIBILITY must be a string that names the visibility for a PHP @@ -242,22 +242,25 @@ which will be the name of the method." (setq visibility (list visibility))) (rx-to-string `(: line-start (* (syntax whitespace)) - ,@(if visibility - `((* (or "abstract" "final" "static") - (+ (syntax whitespace))) - (or ,@visibility) - (+ (syntax whitespace)) - (* (or "abstract" "final" "static") - (+ (syntax whitespace)))) - '((* (* (or "abstract" "final" "static" - "private" "protected" "public") - (+ (syntax whitespace)))))) - "function" - (+ (syntax whitespace)) - (? "&" (* (syntax whitespace))) - (group (+ (or (syntax word) (syntax symbol)))) - (* (syntax whitespace)) - "("))) + (group + ,@(if visibility + `((* (or "abstract" "final" "static") + (+ (syntax whitespace))) + (or ,@visibility) + (+ (syntax whitespace)) + (* (or "abstract" "final" "static") + (+ (syntax whitespace)))) + '((* (* (or "abstract" "final" "static" + "private" "protected" "public") + (+ (syntax whitespace)))))) + "function" + (+ (syntax whitespace)) + (? "&" (* (syntax whitespace))) + (group (+ (or (syntax word) (syntax symbol)))) + (* (syntax whitespace)) + "(" + ,@(when include-args + '((* any) line-end)))))) (defun php-create-regexp-for-classlike (type) "Accepts a `TYPE' of a 'classlike' object as a string, such as @@ -275,7 +278,101 @@ can be used to match against definitions for that classlike." ;; this is not necessarily correct for all values of `type'. "\\s-+\\(\\(?:\\sw\\|\\\\\\|\\s_\\)+\\)"))) -(defconst php-imenu-generic-expression +(defconst php-imenu-generic-expression-default + (eval-when-compile + `(("Methods" + ,(php-create-regexp-for-method nil :include-args t) 1) + ("Properties" + ,(rx line-start + (* (syntax whitespace)) + (group + (+ (or "public" "protected" "private" "static" "var") + (+ (syntax whitespace))) + (* (? (? (or "|" "?")) + (or "\\" (syntax word) (syntax symbol)) + (+ (syntax whitespace)))) + "$" (+ (or (syntax word) (syntax symbol))) + word-boundary)) + 1) + ("Constants" + ,(rx line-start + (* (syntax whitespace)) + (group + (* (or "public" "protected" "private") + (+ (syntax whitespace))) + "const" + (+ (syntax whitespace)) + (+ (or (syntax word) (syntax symbol))) + (* (syntax whitespace)) + (? "=" (* (syntax whitespace)) + (repeat 0 40 any)))) + 1) + ("Functions" + ,(rx line-start + (* (syntax whitespace)) + (group + "function" + (+ (syntax whitespace)) + (+ (or (syntax word) (syntax symbol))) + (* (syntax whitespace)) + "(" + (repeat 0 100 any))) + 1) + ("Import" + ,(rx line-start + ;; (* (syntax whitespace)) + (group + "use" + (+ (syntax whitespace)) + (repeat 0 100 any))) + 1) + ("Classes" + ,(php-create-regexp-for-classlike "\\(?:class\\|interface\\|trait\\|enum\\)") 0) + ("Namespace" + ,(php-create-regexp-for-classlike "namespace") 1))) + "Imenu generic expression for PHP Mode. See `imenu-generic-expression'.") + +(defconst php-imenu-generic-expression-simple + (eval-when-compile + `(("Methods" + ,(php-create-regexp-for-method nil) 2) + ("Properties" + ,(rx line-start + (* (syntax whitespace)) + (+ (or "public" "protected" "private" "static" "var") + (+ (syntax whitespace))) + (* (? (? (or "|" "?")) + (or "\\" (syntax word) (syntax symbol)) + (+ (syntax whitespace)))) + (group + "$" (+ (or (syntax word) (syntax symbol)))) + word-boundary) + 1) + ("Constants" + ,(rx line-start + (* (syntax whitespace)) + (group + (* (or "public" "protected" "private") + (+ (syntax whitespace))) + "const" + (+ (syntax whitespace)) + (+ (or (syntax word) (syntax symbol))))) + 1) + ("Functions" + ,(rx line-start + (* (syntax whitespace)) + "function" + (+ (syntax whitespace)) + (group + (+ (or (syntax word) (syntax symbol))))) + 1) + ("Classes" + ,(php-create-regexp-for-classlike "\\(?:class\\|interface\\|trait\\|enum\\)") 1) + ("Namespace" + ,(php-create-regexp-for-classlike "namespace") 1))) + "Imenu generic expression for PHP Mode. See `imenu-generic-expression'.") + +(defconst php-imenu-generic-expression-legacy (eval-when-compile `(("Namespaces" ,(php-create-regexp-for-classlike "namespace") 1) @@ -288,17 +385,25 @@ can be used to match against definitions for that classlike." ("All Methods" ,(php-create-regexp-for-method) 1) ("Private Methods" - ,(php-create-regexp-for-method '("private")) 1) + ,(php-create-regexp-for-method '("private")) 2) ("Protected Methods" - ,(php-create-regexp-for-method '("protected")) 1) + ,(php-create-regexp-for-method '("protected")) 2) ("Public Methods" - ,(php-create-regexp-for-method '("public")) 1) + ,(php-create-regexp-for-method '("public")) 2) ("Anonymous Functions" "\\<\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*=\\s-*f\\(unctio\\)?n\\s-*(" 1) ("Named Functions" "^\\s-*function\\s-+\\(\\(?:\\sw\\|\\s_\\)+\\)\\s-*(" 1))) "Imenu generic expression for PHP Mode. See `imenu-generic-expression'.") +(defcustom php-imenu-generic-expression 'php-imenu-generic-expression-default + "Default Imenu generic expression for PHP Mode. See `imenu-generic-expression'." + :type '(choice (alist :key-type string :value-type list) + (const 'php-imenu-generic-expression-legacy) + (const 'php-imenu-generic-expression-simple) + variable) + :group 'php) + (defconst php--re-namespace-pattern (eval-when-compile (php-create-regexp-for-classlike "namespace"))) diff --git a/tests/php-mode-test.el b/tests/php-mode-test.el index c53da223..9ee41647 100644 --- a/tests/php-mode-test.el +++ b/tests/php-mode-test.el @@ -319,12 +319,11 @@ style from Drupal." "All static method should appear on imenu whether 'static' keyword is placed before or after visibility" (with-php-mode-test ("issue-83.php") (let* ((index-alist (imenu--make-index-alist)) - (public-methods (mapcar 'car (cdr (assoc "Public Methods" index-alist)))) - (all-methods (mapcar 'car (cdr (assoc "All Methods" index-alist))))) - (should (member "staticBeforeVisibility" public-methods)) - (should (member "staticBeforeVisibility" all-methods)) - (should (member "staticAfterVisibility" public-methods)) - (should (member "staticAfterVisibility" all-methods))))) + (all-methods (mapcar 'car (cdr (assoc "Methods" index-alist))))) + (should (equal all-methods + (list + "static public function staticBeforeVisibility()" + "public static function staticAfterVisibility()")))))) (ert-deftest php-mode-test-issue-99 () "Proper indentation for 'foreach' statements without braces."