[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] scratch/javaimp-wip 4ac5cb4 6/7: wip
From: |
Filipp Gunbin |
Subject: |
[elpa] scratch/javaimp-wip 4ac5cb4 6/7: wip |
Date: |
Wed, 4 Aug 2021 20:42:48 -0400 (EDT) |
branch: scratch/javaimp-wip
commit 4ac5cb48db9fa6d57b937d33a336dcda8cc8c3a1
Author: Filipp Gunbin <fgunbin@fastmail.fm>
Commit: Filipp Gunbin <fgunbin@fastmail.fm>
wip
---
javaimp-parse.el | 13 ++-
javaimp-tests.el | 177 +++++++++++++++++++++++++++++++++++----
javaimp-util.el | 60 ++++++-------
javaimp.el | 65 ++++++++------
testdata/test1-misc-classes.java | 5 ++
5 files changed, 246 insertions(+), 74 deletions(-)
diff --git a/javaimp-parse.el b/javaimp-parse.el
index 1a46b65..061b18d 100644
--- a/javaimp-parse.el
+++ b/javaimp-parse.el
@@ -55,9 +55,14 @@ present."
))
(defsubst javaimp--parse-is-classlike (scope)
- (when scope
- (member (symbol-name (javaimp-scope-type scope))
- javaimp--parse-classlike-keywords)))
+ (and scope
+ (member (symbol-name (javaimp-scope-type scope))
+ javaimp--parse-classlike-keywords)))
+
+(defsubst javaimp--parse-is-named (scope)
+ (and scope
+ (memq (javaimp-scope-type scope)
+ javaimp--parse-named-scope-types)))
(defvar javaimp--arglist-syntax-table
(let ((st (make-syntax-table java-mode-syntax-table))) ;TODO don't depend
@@ -477,7 +482,7 @@ variable after parsing is done."
(and (eq (javaimp-scope-type s) 'method)
(javaimp--parse-is-classlike (javaimp-scope-parent s))))))
(classes (javaimp--parse-get-all-scopes
- nil ;no need to reparse
+ nil ; no need to reparse
#'javaimp--parse-is-classlike))
(top-classes (mapcar (lambda (s)
(null (javaimp-scope-parent s)))
diff --git a/javaimp-tests.el b/javaimp-tests.el
index 7bb63b5..b4788e2 100644
--- a/javaimp-tests.el
+++ b/javaimp-tests.el
@@ -189,34 +189,179 @@ throws E1 {"
"Top.IInner1.IInner1_CInner1"
"Top.IInner1.IInner1_IInner1"
"Top.EInner1"
- "Top.EInner1.EInner1_EInner1")))))
-
-(ert-deftest javaimp-test--parse-get-forest-for-imenu ()
- ;; TODO
- )
-
+ "Top.EInner1.EInner1_EInner1"
+ "ColocatedTop")))))
(ert-deftest javaimp-test--parse-get-all-scopes ()
(with-temp-buffer
(insert-file-contents
(concat javaimp--basedir "testdata/test1-misc-classes.java"))
+ ;;
;; parse full buffer
- (javaimp-test--check-scopes (javaimp--parse-get-all-scopes t))
- ;; reparse half buffer
+ (javaimp-test--check-named-scopes
+ (javaimp--parse-get-all-scopes t #'javaimp--parse-is-named))
+ ;;
+ ;; reparse half of buffer
(setq javaimp--parse-dirty-pos (/ (- (point-max) (point-min)) 2))
- (javaimp-test--check-scopes (javaimp--parse-get-all-scopes))
+ (javaimp-test--check-named-scopes
+ (javaimp--parse-get-all-scopes nil #'javaimp--parse-is-named))
+ ;;
;; use cache
- (javaimp-test--check-scopes (javaimp--parse-get-all-scopes))))
+ (javaimp-test--check-named-scopes
+ (javaimp--parse-get-all-scopes nil #'javaimp--parse-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"))
+
+ ((class "CInner1_CInner") (class "CInner1") (class "Top"))
+ ((method "foo")
+ (class "CInner1_CInner") (class "CInner1") (class "Top"))
+ ((method "bar")
+ (class "CInner1_CInner") (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") (interface "IInner1") (class "Top"))
+
+ ((interface "IInner1_IInner1") (interface "IInner1") (class "Top"))
+ ((method "defaultMethod")
+ (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")))))
+ (should (= (length expected) (length actual)))
+ (dotimes (i (length expected))
+ (should (equal (nth i expected) (nth i actual)))))
+ ;;
+ (let ((data
+ `((,(nth 0 scopes) "Top" 26 36)
+ (,(nth 15 scopes) "Top.IInner1.IInner1_CInner1.foo" 1810 1816)
+ (,(nth 22 scopes) "Top.EnumInner1_EInner1" 2452 2476)
+ (,(nth 24 scopes) "ColocatedTop.foo" 2544 2550))))
+ (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)))))))
-(defun javaimp--test-check-scopes (scopes)
- ;; TODO check positions of first / most nested / last
- '((class "Top"))
- '((class "CInner1") (class "Top"))
- '((method "foo") (class "CInner1") (class "Top"))
+
+;; Tests for imenu function
+
+(ert-deftest javaimp-test--imenu-group ()
+ (let* ((javaimp-imenu-group-methods t)
+ (actual (javaimp-test--imenu-get-index)))
+ (should
+ (equal
+ actual
+ '(("Top"
+ ("CInner1"
+ ("foo" . 98)
+ ("CInner1_CInner1"
+ ("foo" . 1099)
+ ("bar" . 1192)))
+ ("IInner1"
+ ("foo" . 1603)
+ ("IInner1_CInner1"
+ ("foo" . 1810))
+ ("defaultMethod" . 1975)
+ ("IInner1_IInner1"
+ ("defaultMethod" . 2158)))
+ ("EnumInner1"
+ ("EnumInner1" . 2343)
+ ("foo" . 2389)
+ ;; "EnumInner1_EInner1" empty - omitted
+ ))
+ ("ColocatedTop"
+ ("foo" . 2544)))))))
+
+(ert-deftest javaimp-test--imenu-simple ()
+ (let* ((javaimp-imenu-group-methods nil)
+ (actual (javaimp-test--imenu-get-index)))
+ (should
+ (equal
+ actual
+ '(("foo (Top.CInner1)" . 98)
+ ("foo (Top.CInner1.CInner1_CInner1)" . 1099)
+ ("bar" . 1192)
+ ("foo (Top.IInner1)" . 1603)
+ ("foo (Top.IInner1.IInner1_CInner1)" . 1810)
+ ("defaultMethod (Top.IInner1)" . 1975)
+ ("defaultMethod (Top.IInner1.IInner1_IInner1)" . 2158)
+ ("EnumInner1" . 2343)
+ ("foo (Top.EnumInner1)" . 2389)
+ ("foo (ColocatedTop)" . 2544))))))
+
+(ert-deftest javaimp-test--imenu-qualified ()
+ (let* ((javaimp-imenu-group-methods 'qualified)
+ (actual
+ (mapcar (lambda (entry)
+
+ (javaimp-test--imenu-get-index)))
+ (should
+ (equal
- )
+ (lambda (s)
+ (cons (javaimp-scope-name entry) (javaimp-scope-start entry)))
+ actual
+ '(("Top.CInner1.foo" . 98)
+ ("Top.CInner1.CInner1_CInner1.foo" . 1099)
+ ("Top.CInner1.CInner1_CInner1.bar" . 1192)
+ ("Top.IInner1.foo" . 1603)
+ ("Top.IInner1.IInner1_CInner1.foo" . 1810)
+ ("Top.IInner1.defaultMethod" . 1975)
+ ("Top.IInner1.IInner1_IInner1.defaultMethod" . 2158)
+ ("Top.EnumInner1.EnumInner1" . 2343)
+ ("Top.EnumInner1.foo" . 2389)
+ ("ColocatedTop.foo" . 2544))))))
+
+(defun javaimp-test--imenu-get-index ()
+ (with-temp-buffer
+ (insert-file-contents
+ (concat javaimp--basedir "testdata/test1-misc-classes.java"))
+ (javaimp-imenu-create-index)))
(provide 'javaimp-tests)
diff --git a/javaimp-util.el b/javaimp-util.el
index f2b4dda..1bf2a79 100644
--- a/javaimp-util.el
+++ b/javaimp-util.el
@@ -157,57 +157,59 @@ PARENT-NODE is indented for recursive calls."
(setf (javaimp-node-children this-node) child-nodes)
this-node)))
-(defun javaimp--find-node (predicate forest &optional unwrap)
+(defun javaimp--find-node (pred forest &optional unwrap)
(catch 'found
(dolist (tree forest)
- (javaimp--find-node-in-tree-1 tree predicate unwrap))))
+ (javaimp--find-node-in-tree-1 tree pred unwrap))))
-(defun javaimp--find-node-in-tree-1 (tree predicate unwrap)
+(defun javaimp--find-node-in-tree-1 (tree pred unwrap)
(when tree
- (if (funcall predicate (javaimp-node-contents tree))
+ (if (funcall 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-1 child predicate unwrap))))
+ (javaimp--find-node-in-tree-1 child pred unwrap))))
-(defun javaimp--collect-nodes (predicate forest &optional unwrap)
+(defun javaimp--collect-nodes (pred forest)
(apply #'seq-concatenate 'list
(mapcar (lambda (tree)
- (javaimp--collect-nodes-from-tree tree predicate unwrap))
+ (javaimp--collect-nodes-from-tree tree pred))
forest)))
-(defun javaimp--collect-nodes-from-tree (tree predicate unwrap)
+(defun javaimp--collect-nodes-from-tree (tree pred)
(when tree
- (append (when (funcall predicate (javaimp-node-contents tree))
- (list (if unwrap
- (javaimp-node-contents tree)
- tree)))
+ (append (when (funcall pred (javaimp-node-contents tree))
+ (list (javaimp-node-contents tree)))
(apply #'seq-concatenate 'list
(mapcar (lambda (child)
- (javaimp--collect-nodes-from-tree
- child predicate unwrap))
+ (javaimp--collect-nodes-from-tree child pred))
(javaimp-node-children tree))))))
-(defun javaimp--map-nodes (mapper forest &optional unwrap)
- (mapcar (lambda (tree)
- (javaimp--map-nodes-from-tree tree mapper unwrap))
- forest))
-(defun javaimp--map-nodes-from-tree (tree mapper unwrap)
+(defun javaimp--map-nodes (mapper pred forest)
+ "Recursively applies MAPPER to each node's contents in FOREST.
+Returns new tree where each node is of the form (MAPPED-NODE
+. CHILDREN). A node is included only if PRED applied to it
+returns non-nil."
+ (delq nil
+ (mapcar (lambda (tree)
+ (javaimp--map-nodes-from-tree tree mapper pred))
+ forest)))
+
+(defun javaimp--map-nodes-from-tree (tree mapper pred)
(when tree
- (cons (let ((contents (funcall mapper (javaimp-node-contents tree))))
- (if unwrap
- contents
- (make-javaimp-node
- :parent (javaimp-node-parent tree)
- :children (javaimp-node-children tree)
- :contents contents)))
- (mapcar (lambda (child)
- (javaimp--map-nodes-from-tree child mapper unwrap))
- (javaimp-node-children tree)))))
+ (let* ((contents (funcall mapper (javaimp-node-contents tree)))
+ (children
+ (delq nil
+ (mapcar (lambda (child)
+ (javaimp--map-nodes-from-tree child mapper pred))
+ (javaimp-node-children tree))))
+ (res (cons contents children)))
+ (and (funcall pred res)
+ res))))
(defun javaimp--get-root (node)
(while (javaimp-node-parent node)
diff --git a/javaimp.el b/javaimp.el
index 5d9ef9d..86b16cd 100644
--- a/javaimp.el
+++ b/javaimp.el
@@ -310,14 +310,10 @@ PREDICATE returns non-nil."
(defun javaimp-collect-modules (predicate)
"Returns all modules in `javaimp-project-forest' for which
PREDICATE returns non-nil."
- (javaimp--collect-nodes predicate javaimp-project-forest t))
+ (javaimp--collect-nodes predicate javaimp-project-forest))
(defun javaimp-map-modules (mapper)
- "Applies MAPPER to all modules in `javaimp-project-forest' and
-returns the result as a tree-like structure: a list of
-conses (CONTENTS . CHILDREN) where CHILDREN have the same
-structure, and so on."
- (javaimp--map-nodes mapper javaimp-project-forest t))
+ (javaimp--map-nodes mapper #'always javaimp-project-forest))
;;; Adding imports
@@ -577,24 +573,31 @@ is `ordinary' or `static'. Interactively, NEW-IMPORTS is
nil."
(let ((forest (save-excursion
(javaimp--parse-get-forest-for-imenu))))
(cond ((not javaimp-imenu-group-methods)
- ;; just plain list of methods
- (javaimp--collect-nodes
- (lambda (scope)
- (when (eq (javaimp-scope-type scope) 'method)
- (javaimp-imenu--make-entry scope)))
- forest t))
+ ;; plain list of methods
+ (let ((entries (mapcar #'javaimp-imenu--make-entry
+ (javaimp--collect-nodes
+ #'javaimp-imenu--included-method forest))))
+ (mapcar (lambda (entry)
+ ;; disambiguate similar method names
+ (when (assoc (car entry) entries)
+ (setcar entry
+ (format "%s (%s)"
+ (car entry)
+ (javaimp-imenu--concat-parent-names
+ (nth 3 entry))))))
+ entries)))
((eq javaimp-imenu-group-methods 'qualified)
;; list of qualified methods
- (javaimp--collect-nodes
- (lambda (scope)
- (when (eq (javaimp-scope-type scope) 'method)
- (let ((entry (javaimp-imenu--make-entry scope)))
- ;; prepend parents to name
- (while (setq scope (javaimp-scope-parent scope))
- (setcar entry (concat (javaimp-scope-name scope)
- "."
- (car entry)))))))
- forest t))
+ (mapcar (lambda (entry)
+ ;; prepend parents to name
+ (setcar entry (concat (javaimp-imenu--concat-parent-names
+ (nth 3 entry))
+ "."
+ (car entry))))
+ (mapcar #'javaimp-imenu-make-entry
+ (javaimp--collect-nodes
+ #'javaimp-imenu--included-method forest))))
+
(t
;; group methods inside their enclosing class
(javaimp--map-nodes
@@ -602,16 +605,28 @@ is `ordinary' or `static'. Interactively, NEW-IMPORTS is
nil."
(cond ((javaimp--parse-is-classlike scope)
;; this will be a sub-alist's car
(javaimp-scope-name scope))
- ((eq (javaimp-scope-type scope) 'method)
+ ((javaimp-imenu--included-method scope)
(javaimp-imenu--make-entry scope))))
- forest t)))))
+ #'cdr ;don't include empty container scopes
+ forest)))))
-(defun javaimp-imenu--make-entry (scope)
+(defsubst javaimp-imenu--included-method (scope)
+ (and (eq (javaimp-scope-type scope) 'method)
+ (javaimp--parse-is-classlike (javaimp-scope-parent scope))))
+
+(defsubst javaimp-imenu--make-entry (scope)
(list (javaimp-scope-name scope)
(javaimp-scope-start scope)
#'javaimp-imenu--go
scope))
+(defun javaimp-imenu--concat-parent-names (scope)
+ (let (parents)
+ (while (setq scope (javaimp-scope-parent scope))
+ (push scope parents))
+ (mapconcat #'javaimp-scope-name parents ".")))
+
+
(defun javaimp-imenu--go (scope)
(goto-char (javaimp-scope-start scope))
(back-to-indentation))
diff --git a/testdata/test1-misc-classes.java b/testdata/test1-misc-classes.java
index 436d057..d916221 100644
--- a/testdata/test1-misc-classes.java
+++ b/testdata/test1-misc-classes.java
@@ -115,3 +115,8 @@ public class Top {
}
}
}
+
+class ColocatedTop {
+ void foo() {
+ }
+}
- [elpa] branch scratch/javaimp-wip created (now dcc6bed), Filipp Gunbin, 2021/08/04
- [elpa] scratch/javaimp-wip 86cd3b9 1/7: wip, Filipp Gunbin, 2021/08/04
- [elpa] scratch/javaimp-wip 551b1a3 2/7: wip, Filipp Gunbin, 2021/08/04
- [elpa] scratch/javaimp-wip a5c00a7 3/7: wip, Filipp Gunbin, 2021/08/04
- [elpa] scratch/javaimp-wip aa0f932 4/7: wip, Filipp Gunbin, 2021/08/04
- [elpa] scratch/javaimp-wip dcc6bed 7/7: wip, Filipp Gunbin, 2021/08/04
- [elpa] scratch/javaimp-wip fe080eb 5/7: wip, Filipp Gunbin, 2021/08/04
- [elpa] scratch/javaimp-wip 4ac5cb4 6/7: wip,
Filipp Gunbin <=