[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/javaimp 691f0ec 2/2: Imenu & scopes improvements
From: |
Filipp Gunbin |
Subject: |
[elpa] externals/javaimp 691f0ec 2/2: Imenu & scopes improvements |
Date: |
Fri, 27 Aug 2021 13:48:24 -0400 (EDT) |
branch: externals/javaimp
commit 691f0ec7a0aee8f598bae969508c0b7b3966c7d6
Author: Filipp Gunbin <fgunbin@fastmail.fm>
Commit: Filipp Gunbin <fgunbin@fastmail.fm>
Imenu & scopes improvements
---
javaimp-parse.el | 83 ++++++++--------------
javaimp-tests.el | 204 +++++++++++++++++++++++++++----------------------------
javaimp-util.el | 61 ++++++++---------
javaimp.el | 97 +++++++++++++++++++-------
4 files changed, 230 insertions(+), 215 deletions(-)
diff --git a/javaimp-parse.el b/javaimp-parse.el
index 460e615..130edff 100644
--- a/javaimp-parse.el
+++ b/javaimp-parse.el
@@ -208,8 +208,7 @@ is unchanged."
the position of opening brace.")
(defun javaimp--parse-scope-class (brace-pos)
- "Attempts to parse 'class' / 'interface' / 'enum' scope. Some of
-those may later become 'local-class' (see `javaimp--parse-scopes')."
+ "Attempts to parse 'class' / 'interface' / 'enum' scope."
(save-excursion
(if (javaimp--parse-preceding (regexp-opt
javaimp--parse-classlike-keywords 'symbols)
brace-pos)
@@ -334,8 +333,9 @@ those may later become 'local-class' (see
`javaimp--parse-scopes')."
:open-brace brace-pos))
(defun javaimp--parse-scopes (count)
- "Attempts to parse COUNT enclosing scopes at point. If COUNT is
-nil then goes all the way up. Examines and sets property
+ "Attempts to parse COUNT enclosing scopes at point. Returns most
+nested one, with its parents sets accordingly. If COUNT is nil
+then goes all the way up. Examines and sets property
'javaimp-parse-scope' at each scope's open brace."
(let ((state (syntax-ppss))
res)
@@ -356,19 +356,12 @@ nil then goes all the way up. Examines and sets property
(if (javaimp-scope-start scope)
(goto-char (javaimp-scope-start scope)))))
(setq state (syntax-ppss))))
- ;; if a class is enclosed in anything other than a class, then it
- ;; should be local
- (let ((tmp res)
- in-local parent)
- (while tmp
- (if (javaimp--is-classlike (car tmp))
- (when in-local
- (setf (javaimp-scope-type (car tmp)) 'local-class))
- (setq in-local t))
- (setf (javaimp-scope-parent (car tmp)) parent)
- (setq parent (car tmp))
- (setq tmp (cdr tmp))))
- res))
+ (let (parent)
+ (while res
+ (setf (javaimp-scope-parent (car res)) parent)
+ (setq parent (car res))
+ (setq res (cdr res)))
+ parent)))
(defun javaimp--parse-all-scopes ()
"Entry point to the scope parsing. Parses scopes in this
@@ -403,20 +396,26 @@ non-nil. Resets this variable after parsing is done."
(javaimp--parse-rsb-keyword ";" nil t -1)
;; we're in the same nest
(= (nth 1 (syntax-ppss)) enclosing))
- (backward-char) ;skip semicolon
+ (backward-char) ;skip semicolon
;; now parse as normal method scope
(when-let ((scope (javaimp--parse-scope-method-or-stmt (point)))
- ;; note that an abstract method with no parents
- ;; will be ignored
- (parents (javaimp--parse-scopes nil)))
- (setf (javaimp-scope-parent scope) (car (last parents)))
+ ;; note that an abstract method with no
+ ;; parents will be ignored
+ (parent (javaimp--parse-scopes nil)))
+ (setf (javaimp-scope-parent scope) (javaimp--copy-scope
parent))
(push scope res)))))))
res))
+(defun javaimp--parse-abstract-interface-methods ()
+ ;; TODO
+ )
+
+
;; Functions intended to be called from other parts of javaimp.
(defun javaimp--parse-get-package ()
+ "Return the package declared in the current file."
(save-excursion
(save-restriction
(widen)
@@ -425,39 +424,6 @@ non-nil. Resets this variable after parsing is done."
"^[ \t]*package[ \t]+\\([^ \t;\n]+\\)[ \t]*;" nil t 1)
(match-string 1)))))
-(defun javaimp--parse-get-all-classlikes ()
- (mapcar (lambda (scope)
- (let ((name (javaimp-scope-name scope))
- (parent-names (javaimp--concat-scope-parents scope)))
- (if (string-empty-p parent-names)
- name
- (concat parent-names "." name))))
- (javaimp--parse-get-all-scopes #'javaimp--is-classlike)))
-
-(defun javaimp--parse-get-imenu-forest ()
- (let* ((methods (javaimp--parse-get-all-scopes
- #'javaimp--is-imenu-included-method
#'javaimp--is-classlike))
- (classes (javaimp--parse-get-all-scopes #'javaimp--is-classlike))
- (top-classes (seq-filter (lambda (s)
- (null (javaimp-scope-parent s)))
- classes))
- (ac-methods (javaimp--parse-abstract-class-methods)))
- (mapcar
- (lambda (top-class)
- (message "Building tree for top-level class-like scope: %s"
- (javaimp-scope-name top-class))
- (javaimp--build-tree top-class
- (append methods
- classes
- ac-methods)
- (lambda (el tested)
- (equal el (javaimp-scope-parent tested)))
- nil
- (lambda (s1 s2)
- (< (javaimp-scope-start s1)
- (javaimp-scope-start s2)))))
- top-classes)))
-
(defun javaimp--parse-get-all-scopes (&optional pred parent-pred)
"Return all scopes in the current buffer, optionally filtering
them with PRED, and their parents with PARENT-PRED. Neither of
@@ -479,6 +445,13 @@ them should move point."
(push scope res)))
res))))
+(defun javaimp--parse-abstract-methods ()
+ (save-excursion
+ (save-restriction
+ (widen)
+ (append (javaimp--parse-abstract-class-methods)
+ (javaimp--parse-abstract-interface-methods)))))
+
(defun javaimp--parse-update-dirty-pos (beg _end _old-len)
"Function to add to `after-change-functions' hook."
(when (or (not javaimp--parse-dirty-pos)
diff --git a/javaimp-tests.el b/javaimp-tests.el
index 06162fa..93dfcc4 100644
--- a/javaimp-tests.el
+++ b/javaimp-tests.el
@@ -173,7 +173,7 @@ throws E1 {"
(should (equal (javaimp-scope-name (car scopes)) (nth 2 item)))))))
-;; Tests for javaimp-parse.el "package-private" API.
+;; Tests for parsing
(ert-deftest javaimp-test--parse-get-package ()
(with-temp-buffer
@@ -185,126 +185,107 @@ package commented.block;
(setq syntax-ppss-table javaimp-syntax-table)
(should (equal (javaimp--parse-get-package) "foo.bar.baz"))))
-(ert-deftest javaimp-test--parse-get-all-classlikes ()
- (with-temp-buffer
- (insert-file-contents
- (concat javaimp--basedir "testdata/test1-misc-classes.java"))
- (setq syntax-ppss-table javaimp-syntax-table)
- (setq javaimp--parse-dirty-pos (point-min))
- (should (equal (javaimp--parse-get-all-classlikes)
- '("Top"
- "Top.CInner1"
- "Top.CInner1.CInner1_CInner1"
- "Top.IInner1"
- "Top.IInner1.IInner1_CInner1"
- "Top.IInner1.IInner1_IInner1"
- "Top.EnumInner1"
- "Top.EnumInner1.EnumInner1_EInner1"
- "ColocatedTop")))))
-
(ert-deftest javaimp-test--parse-get-all-scopes ()
(with-temp-buffer
(insert-file-contents
(concat javaimp--basedir "testdata/test1-misc-classes.java"))
(setq syntax-ppss-table javaimp-syntax-table)
(let ((javaimp-format-method-name #'javaimp-format-method-name-types))
- ;;
;; parse full buffer
(setq javaimp--parse-dirty-pos (point-min))
- (javaimp-test--check-named-scopes
- (javaimp--parse-get-all-scopes
- #'javaimp--is-named #'javaimp--is-named))
+ (javaimp-test--check-named-scopes)
;;
;; reparse half of buffer
(setq javaimp--parse-dirty-pos (/ (- (point-max) (point-min)) 2))
- (javaimp-test--check-named-scopes
- (javaimp--parse-get-all-scopes
- #'javaimp--is-named #'javaimp--is-named))
+ (javaimp-test--check-named-scopes)
;;
;; don't reparse
- (javaimp-test--check-named-scopes
- (javaimp--parse-get-all-scopes
- #'javaimp--is-named #'javaimp--is-named)))))
-
-(defun javaimp-test--check-named-scopes (scopes)
- (let ((actual
- (mapcar (lambda (s)
- (let (res)
- (while s
- (push (list (javaimp-scope-type s)
- (javaimp-scope-name s))
- res)
- (setq s (javaimp-scope-parent s)))
- (nreverse res)))
- scopes))
- (expected
- '(((class "Top"))
- ((class "CInner1") (class "Top"))
- ((method "foo()") (class "CInner1") (class "Top"))
- ((local-class "CInner1_CLocal1")
- (method "foo()") (class "CInner1") (class "Top"))
- ((method "foo()")
- (local-class "CInner1_CLocal1")
- (method "foo()") (class "CInner1") (class "Top"))
- ((local-class "CInner1_CLocal1_CLocal1")
- (method "foo()")
- (local-class "CInner1_CLocal1")
- (method "foo()") (class "CInner1") (class "Top"))
- ((method "foo()")
- (local-class "CInner1_CLocal1_CLocal1")
- (method "foo()")
- (local-class "CInner1_CLocal1")
- (method "foo()") (class "CInner1") (class "Top"))
-
- ((local-class "CInner1_CLocal2")
- (method "foo()") (class "CInner1") (class "Top"))
- ((method "foo()")
- (local-class "CInner1_CLocal2")
- (method "foo()") (class "CInner1") (class "Top"))
-
- ((method "toString()")
- (class "CInner1") (class "Top"))
-
- ((class "CInner1_CInner1") (class "CInner1") (class "Top"))
- ((method "foo()")
- (class "CInner1_CInner1") (class "CInner1") (class "Top"))
- ((method "bar()")
- (class "CInner1_CInner1") (class "CInner1") (class "Top"))
-
- ((interface "IInner1") (class "Top"))
- ((method "foo()") (interface "IInner1") (class "Top"))
- ((class "IInner1_CInner1") (interface "IInner1") (class "Top"))
- ((method "foo()")
- (class "IInner1_CInner1") (interface "IInner1") (class "Top"))
- ((method "defaultMethod(String)")
- (interface "IInner1") (class "Top"))
-
- ((interface "IInner1_IInner1") (interface "IInner1") (class "Top"))
- ((method "defaultMethod(String)")
- (interface "IInner1_IInner1") (interface "IInner1") (class "Top"))
-
- ((enum "EnumInner1") (class "Top"))
- ((method "EnumInner1()") (enum "EnumInner1") (class "Top"))
- ((method "foo()") (enum "EnumInner1") (class "Top"))
- ((enum "EnumInner1_EInner1") (enum "EnumInner1") (class "Top"))
-
- ((class "ColocatedTop"))
- ((method "foo()") (class "ColocatedTop"))
- ((method "bar(String, String)") (class "ColocatedTop")))))
+ (javaimp-test--check-named-scopes))))
+
+(defun javaimp-test--check-named-scopes ()
+ (let* ((scopes (javaimp--parse-get-all-scopes
+ (lambda (scope)
+ (memq (javaimp-scope-type scope) '(class interface enum
method)))
+ (lambda (scope)
+ (memq (javaimp-scope-type scope) '(class interface enum
method)))))
+ (actual (mapcar
+ (lambda (s)
+ (let (res)
+ (while s
+ (push (list (javaimp-scope-type s)
+ (javaimp-scope-name s))
+ res)
+ (setq s (javaimp-scope-parent s)))
+ (nreverse res)))
+ scopes))
+ (expected
+ '(((class "Top"))
+ ((class "CInner1") (class "Top"))
+ ((method "foo()") (class "CInner1") (class "Top"))
+ ((class "CInner1_CLocal1")
+ (method "foo()") (class "CInner1") (class "Top"))
+ ((method "foo()")
+ (class "CInner1_CLocal1")
+ (method "foo()") (class "CInner1") (class "Top"))
+ ((class "CInner1_CLocal1_CLocal1")
+ (method "foo()")
+ (class "CInner1_CLocal1")
+ (method "foo()") (class "CInner1") (class "Top"))
+ ((method "foo()")
+ (class "CInner1_CLocal1_CLocal1")
+ (method "foo()")
+ (class "CInner1_CLocal1")
+ (method "foo()") (class "CInner1") (class "Top"))
+
+ ((class "CInner1_CLocal2")
+ (method "foo()") (class "CInner1") (class "Top"))
+ ((method "foo()")
+ (class "CInner1_CLocal2")
+ (method "foo()") (class "CInner1") (class "Top"))
+
+ ((method "toString()")
+ (class "CInner1") (class "Top"))
+
+ ((class "CInner1_CInner1") (class "CInner1") (class "Top"))
+ ((method "foo()")
+ (class "CInner1_CInner1") (class "CInner1") (class "Top"))
+ ((method "bar()")
+ (class "CInner1_CInner1") (class "CInner1") (class "Top"))
+
+ ((interface "IInner1") (class "Top"))
+ ((method "foo()") (interface "IInner1") (class "Top"))
+ ((class "IInner1_CInner1") (interface "IInner1") (class "Top"))
+ ((method "foo()")
+ (class "IInner1_CInner1") (interface "IInner1") (class "Top"))
+ ((method "defaultMethod(String)")
+ (interface "IInner1") (class "Top"))
+
+ ((interface "IInner1_IInner1") (interface "IInner1") (class "Top"))
+ ((method "defaultMethod(String)")
+ (interface "IInner1_IInner1") (interface "IInner1") (class "Top"))
+
+ ((enum "EnumInner1") (class "Top"))
+ ((method "EnumInner1()") (enum "EnumInner1") (class "Top"))
+ ((method "foo()") (enum "EnumInner1") (class "Top"))
+ ((enum "EnumInner1_EInner1") (enum "EnumInner1") (class "Top"))
+
+ ((class "ColocatedTop"))
+ ((method "foo()") (class "ColocatedTop"))
+ ((method "bar(String, String)") (class "ColocatedTop")))))
(should (= (length expected) (length actual)))
(dotimes (i (length expected))
- (should (equal (nth i expected) (nth i actual)))))
- ;;
- (let ((data
+ (should (equal (nth i expected) (nth i actual))))
+ ;;
+ (let ((data
`((,(nth 0 scopes) "Top" 26 36)
(,(nth 16 scopes) "foo()" 1798 1804)
(,(nth 23 scopes) "EnumInner1_EInner1" 2462 2486)
(,(nth 25 scopes) "foo()" 2554 2560))))
- (dolist (elt data)
- (let ((scope (nth 0 elt)))
- (should (equal (nth 1 elt) (javaimp-scope-name scope)))
- (should (equal (nth 2 elt) (javaimp-scope-start scope)))
- (should (equal (nth 3 elt) (javaimp-scope-open-brace scope)))))))
+ (dolist (elt data)
+ (let ((scope (nth 0 elt)))
+ (should (equal (nth 1 elt) (javaimp-scope-name scope)))
+ (should (equal (nth 2 elt) (javaimp-scope-start scope)))
+ (should (equal (nth 3 elt) (javaimp-scope-open-brace scope))))))))
@@ -404,4 +385,23 @@ package commented.block;
(dotimes (i (length expected-names))
(should (equal (nth i expected-names) (car (nth i actual)))))))
+
+(ert-deftest javaimp-test--get-file-classes ()
+ (with-temp-buffer
+ (insert-file-contents
+ (concat javaimp--basedir "testdata/test1-misc-classes.java"))
+ (setq syntax-ppss-table javaimp-syntax-table)
+ (setq javaimp--parse-dirty-pos (point-min))
+ (should (equal (javaimp--get-file-classes-1)
+ '("org.foo.Top"
+ "org.foo.Top.CInner1"
+ "org.foo.Top.CInner1.CInner1_CInner1"
+ "org.foo.Top.IInner1"
+ "org.foo.Top.IInner1.IInner1_CInner1"
+ "org.foo.Top.IInner1.IInner1_IInner1"
+ "org.foo.Top.EnumInner1"
+ "org.foo.Top.EnumInner1.EnumInner1_EInner1"
+ "org.foo.ColocatedTop")))))
+
+
(provide 'javaimp-tests)
diff --git a/javaimp-util.el b/javaimp-util.el
index 588e8bf..15052d2 100644
--- a/javaimp-util.el
+++ b/javaimp-util.el
@@ -32,15 +32,16 @@
(defconst javaimp--classlike-scope-types
'(class interface enum))
-(defconst javaimp--named-scope-types
- (append
- '(local-class method)
- javaimp--classlike-scope-types))
-
(defconst javaimp--all-scope-types
(append
- '(anonymous-class statement simple-statement array unknown)
- javaimp--named-scope-types))
+ '(anonymous-class
+ array
+ method
+ simple-statement
+ statement
+ array
+ unknown)
+ javaimp--classlike-scope-types))
(defconst javaimp--help-scope-type-abbrevs
'((anonymous-class . "ac")
@@ -48,7 +49,6 @@
(simple-statement . "ss")
(array . "ar")
(unknown . "un")
- (local-class . "lc")
(method . "me")
(class . "cl")
(interface . "in")
@@ -109,20 +109,6 @@
;; Scopes
-(defsubst javaimp--is-classlike (scope)
- (and scope
- (memq (javaimp-scope-type scope)
- javaimp--classlike-scope-types)))
-
-(defsubst javaimp--is-named (scope)
- (and scope
- (memq (javaimp-scope-type scope)
- javaimp--named-scope-types)))
-
-(defsubst javaimp--is-imenu-included-method (scope)
- (and (eq (javaimp-scope-type scope) 'method)
- (javaimp--is-classlike (javaimp-scope-parent scope))))
-
(defun javaimp--copy-scope (scope)
"Recursively copies SCOPE and its parents."
(let* ((res (copy-javaimp-scope scope))
@@ -150,6 +136,13 @@ left."
(push scope parents))
(mapconcat #'javaimp-scope-name parents ".")))
+(defsubst javaimp-test-scope-type (scope leaf-types parent-types)
+ (declare (indent 1))
+ (let ((res (memq (javaimp-scope-type scope) leaf-types)))
+ (while (and res
+ (setq scope (javaimp-scope-parent scope)))
+ (setq res (memq (javaimp-scope-type scope) parent-types)))
+ res))
;;; Formatting
@@ -202,37 +195,41 @@ recursive calls."
(setf (javaimp-node-children this-node) child-nodes)
this-node)))
-(defun javaimp--find-node (pred forest &optional unwrap)
+(defun javaimp--find-node (contents-pred forest &optional unwrap)
+ "Return first node for which CONTENTS-PRED returns non-nil. If
+UNWRAP is non-nil, then node contents is returned."
(catch 'found
(dolist (tree forest)
- (javaimp--find-node-in-tree tree pred unwrap))))
+ (javaimp--find-node-in-tree tree contents-pred unwrap))))
-(defun javaimp--find-node-in-tree (tree pred unwrap)
+(defun javaimp--find-node-in-tree (tree contents-pred unwrap)
(when tree
- (if (funcall pred (javaimp-node-contents tree))
+ (if (funcall contents-pred (javaimp-node-contents tree))
(throw 'found
(if unwrap
(javaimp-node-contents tree)
tree)))
(dolist (child (javaimp-node-children tree))
- (javaimp--find-node-in-tree child pred unwrap))))
+ (javaimp--find-node-in-tree child contents-pred unwrap))))
-(defun javaimp--collect-nodes (pred forest)
+(defun javaimp--collect-nodes (contents-pred forest)
+ "Return all nodes' contents for which CONTENTS-PRED returns
+non-nil."
(apply #'seq-concatenate 'list
(mapcar (lambda (tree)
(delq nil
- (javaimp--collect-nodes-from-tree tree pred)))
+ (javaimp--collect-nodes-from-tree tree contents-pred)))
forest)))
-(defun javaimp--collect-nodes-from-tree (tree pred)
+(defun javaimp--collect-nodes-from-tree (tree contents-pred)
(when tree
- (cons (and (funcall pred (javaimp-node-contents tree))
+ (cons (and (funcall contents-pred (javaimp-node-contents tree))
(javaimp-node-contents tree))
(apply #'seq-concatenate 'list
(mapcar (lambda (child)
(delq nil
- (javaimp--collect-nodes-from-tree child pred)))
+ (javaimp--collect-nodes-from-tree child
contents-pred)))
(javaimp-node-children tree))))))
diff --git a/javaimp.el b/javaimp.el
index c8c7bc8..cf77216 100644
--- a/javaimp.el
+++ b/javaimp.el
@@ -465,11 +465,11 @@ prefix arg is given, don't do this filtering."
default-directory))))
(defun javaimp--get-directory-classes (dir)
- (if (file-accessible-directory-p dir)
- (seq-mapcat #'javaimp--get-file-classes
- (seq-filter (lambda (file)
- (not (file-symlink-p file)))
- (directory-files-recursively dir
"\\.java\\'")))))
+ (when (file-accessible-directory-p dir)
+ (seq-mapcat #'javaimp--get-file-classes
+ (seq-filter (lambda (file)
+ (not (file-symlink-p file)))
+ (directory-files-recursively dir "\\.java\\'")))))
(defun javaimp--get-file-classes (file)
(let ((buf (seq-find (lambda (b) (equal (buffer-file-name b) file))
@@ -483,12 +483,25 @@ prefix arg is given, don't do this filtering."
(javaimp--get-file-classes-1)))))
(defun javaimp--get-file-classes-1 ()
- (let ((package (javaimp--parse-get-package)))
+ "Return fully-qualified names of all class-like scopes."
+ (let ((package (javaimp--parse-get-package))
+ (scopes (javaimp--parse-get-all-scopes
+ (lambda (scope)
+ (javaimp-test-scope-type scope
+ javaimp--classlike-scope-types
+ javaimp--classlike-scope-types)))))
(mapcar (lambda (class)
(if package
(concat package "." class)
class))
- (javaimp--parse-get-all-classlikes))))
+ (mapcar (lambda (scope)
+ (let ((name (javaimp-scope-name scope))
+ (parent-names (javaimp--concat-scope-parents
scope)))
+ (if (string-empty-p parent-names)
+ name
+ (concat parent-names "." name))))
+ scopes))))
+
;; Organizing imports
@@ -624,15 +637,10 @@ the `java-mode-hook':
In future, when we implement a minor / major mode, it will be
done in mode functions automatically."
- (let ((forest (javaimp--parse-get-imenu-forest)))
+ (let ((forest (javaimp-imenu--get-forest)))
(cond ((not javaimp-imenu-group-methods)
;; plain list of methods
- (let ((entries
- (mapcar #'javaimp-imenu--make-entry
- (seq-sort-by
- #'javaimp-scope-start #'<
- (javaimp--collect-nodes
- #'javaimp--is-imenu-included-method forest))))
+ (let ((entries (javaimp-imenu--make-entries-simple forest))
name-alist)
(mapc (lambda (entry)
(setf (alist-get (car entry) name-alist 0 nil #'equal)
@@ -655,27 +663,64 @@ done in mode functions automatically."
(nth 3 entry))
"."
(car entry))))
- (mapcar #'javaimp-imenu--make-entry
- (seq-sort-by
- #'javaimp-scope-start #'<
- (javaimp--collect-nodes
- #'javaimp--is-imenu-included-method forest)))))
-
+ (javaimp-imenu--make-entries-simple forest)))
(t
;; group methods inside their enclosing class
(javaimp--map-nodes
(lambda (scope)
- (cond ((javaimp--is-classlike scope)
- ;; sub-alist
- (cons t (javaimp-scope-name scope)))
- ((javaimp--is-imenu-included-method scope)
- ;; entry
- (cons nil (javaimp-imenu--make-entry scope)))))
+ (if (eq (javaimp-scope-type scope) 'method)
+ ;; entry
+ (cons nil (javaimp-imenu--make-entry scope))
+ ;; sub-alist
+ (cons t (javaimp-scope-name scope))))
(lambda (res)
(or (functionp (nth 2 res)) ;entry
(cdr res))) ;non-empty sub-alist
forest)))))
+(defun javaimp-imenu--get-forest ()
+ (let* ((scopes
+ (javaimp--parse-get-all-scopes
+ (lambda (scope)
+ (javaimp-test-scope-type scope
+ '(class interface enum method)
+ javaimp--classlike-scope-types))))
+ (methods (seq-filter
+ (lambda (scope)
+ (eq (javaimp-scope-type scope) 'method))
+ scopes))
+ (classes (seq-filter
+ (lambda (scope)
+ (not (eq (javaimp-scope-type scope) 'method)))
+ scopes))
+ (top-classes (seq-filter (lambda (s)
+ (null (javaimp-scope-parent s)))
+ classes))
+ (abstract-methods (javaimp--parse-abstract-methods)))
+ (mapcar
+ (lambda (top-class)
+ (message "Building tree for top-level class-like scope: %s"
+ (javaimp-scope-name top-class))
+ (javaimp--build-tree top-class
+ (append methods
+ classes
+ abstract-methods)
+ (lambda (el tested)
+ (equal el (javaimp-scope-parent tested)))
+ nil
+ (lambda (s1 s2)
+ (< (javaimp-scope-start s1)
+ (javaimp-scope-start s2)))))
+ top-classes)))
+
+(defun javaimp-imenu--make-entries-simple (forest)
+ (mapcar #'javaimp-imenu--make-entry
+ (seq-sort-by #'javaimp-scope-start #'<
+ (javaimp--collect-nodes
+ (lambda (scope)
+ (eq (javaimp-scope-type scope) 'method))
+ forest))))
+
(defsubst javaimp-imenu--make-entry (scope)
(list (javaimp-scope-name scope)
(if imenu-use-markers