Skip to content

Improve php-imenu-generic-expression #666

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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'
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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))) \
Expand Down
4 changes: 3 additions & 1 deletion lisp/php-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
147 changes: 126 additions & 21 deletions lisp/php.el
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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")))
Expand Down
11 changes: 5 additions & 6 deletions tests/php-mode-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -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."
Expand Down