emacs-elpa-diffs
[Top][All Lists]
Advanced

[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() {
+    }
+}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]