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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] scratch/javaimp-wip 551b1a3: wip


From: Filipp Gunbin
Subject: [elpa] scratch/javaimp-wip 551b1a3: wip
Date: Mon, 2 Aug 2021 16:34:21 -0400 (EDT)

branch: scratch/javaimp-wip
commit 551b1a3a270612b06fec2db36026b1acebfe078d
Author: Filipp Gunbin <fgunbin@fastmail.fm>
Commit: Filipp Gunbin <fgunbin@fastmail.fm>

    wip
---
 javaimp-gradle.el |  10 ++++-
 javaimp-maven.el  |  11 +++++-
 javaimp-parse.el  |  89 +++++++++++++++++++++++++-----------------
 javaimp-util.el   |  59 ++++++++++++++++++----------
 javaimp.el        | 115 +++++++++++++++++++++++++++++++++++++++++-------------
 5 files changed, 199 insertions(+), 85 deletions(-)

diff --git a/javaimp-gradle.el b/javaimp-gradle.el
index 85e3f2e..e99aab7 100644
--- a/javaimp-gradle.el
+++ b/javaimp-gradle.el
@@ -48,7 +48,15 @@ information."
                             (javaimp--gradle-module-from-alist alist file))
                           alists)))
     ;; first module is always root
-    (javaimp--build-tree (car modules) nil modules)))
+    (message "Building tree for root: %s"
+             (javaimp-print-id (javaimp-module-id (car modules))))
+    (javaimp--build-tree (car modules) modules
+                        ;; more or less reliable way to find children
+                        ;; is to look for modules with "this" as the
+                        ;; parent
+                         (lambda (el tested)
+                           (equal (javaimp-module-parent-id tested)
+                                  (javaimp-module-id el))))))
 
 (defun javaimp--gradle-handler ()
   (goto-char (point-min))
diff --git a/javaimp-maven.el b/javaimp-maven.el
index eee886f..e2c2118 100644
--- a/javaimp-maven.el
+++ b/javaimp-maven.el
@@ -87,7 +87,16 @@ resulting module trees."
                                          modules)))
                        (cdr modules)))))
       (mapcar (lambda (root)
-                (javaimp--build-tree root nil modules))
+                (message "Building tree for root: %s"
+                         (javaimp-print-id (javaimp-module-id root)))
+                (javaimp--build-tree
+                              root modules
+                             ;; more or less reliable way to find
+                             ;; children is to look for modules with
+                             ;; "this" as the parent
+                              (lambda (el tested)
+                                (equal (javaimp-module-parent-id tested)
+                                       (javaimp-module-id el)))))
               roots))))
 
 (defun javaimp--maven-effective-pom-handler ()
diff --git a/javaimp-parse.el b/javaimp-parse.el
index db58e0e..ca8a77c 100644
--- a/javaimp-parse.el
+++ b/javaimp-parse.el
@@ -37,17 +37,19 @@ present."
        ; method, statement, simple-statement, array, unknown
   name
   start
-  open-brace)
+  open-brace
+  parent)
 
-(defconst javaimp--parse-class-keywords
+(defconst javaimp--parse-classlike-keywords
   '("class" "interface" "enum"))
 (defconst javaimp--parse-stmt-keywords
   '("if" "for" "while" "switch" "try" "catch" "finally"
     "static"                            ;static initializer block
     ))
 
-(defsubst javaimp--parse-is-class (scope)
-  (member (symbol-name (javaimp-scope-type scope)) 
javaimp--parse-class-keywords))
+(defsubst javaimp--parse-is-classlike (scope)
+  (member (symbol-name (javaimp-scope-type scope))
+          javaimp--parse-classlike-keywords))
 
 (defvar javaimp--arglist-syntax-table
   (let ((st (make-syntax-table java-mode-syntax-table))) ;TODO don't depend
@@ -265,7 +267,7 @@ is unchanged."
   "Attempts to parse 'class' / 'interface' / 'enum' scope.  Some of
 those may later become 'local-class' (see `javaimp--parse-scopes')."
   (save-excursion
-    (if (javaimp--parse-preceding (regexp-opt javaimp--parse-class-keywords 
'words)
+    (if (javaimp--parse-preceding (regexp-opt 
javaimp--parse-classlike-keywords 'words)
                                   (nth 1 state))
         (let* ((keyword-start (match-beginning 1))
                (keyword-end (match-end 1))
@@ -394,7 +396,7 @@ nil then goes all the way up.  Examines and sets property
         ;; find innermost enclosing open-bracket
         (goto-char (nth 1 state))
         (when (= (char-after) ?{)
-          (let ((scope (get-text-property 'javaimp-parse-scope)))
+          (let ((scope (get-text-property (point) 'javaimp-parse-scope)))
             (unless scope
               (setq scope (run-hook-with-args-until-success
                            'javaimp--parse-scope-hook state))
@@ -407,15 +409,27 @@ nil then goes all the way up.  Examines and sets property
     ;; if a class is enclosed in anything other than a class, then it
     ;; should be local
     (let ((tmp res)
-          in-local)
+          in-local parent)
       (while tmp
-        (if (javaimp--parse-is-class (car tmp))
+        (if (javaimp--parse-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))
 
+
+;; Main
+
+(defun javaimp--parse-get-package ()
+  (goto-char (point-max))
+  (when (javaimp--parse-rsb-keyword
+         "^\\s-*package\\s-+\\([^;\n]+\\)\\s-*;" nil t 1)
+    (match-string 1)))
+
+
 (defun javaimp--parse-all-scopes ()
   "Parses all scopes in a buffer."
   (goto-char (point-max))
@@ -427,50 +441,53 @@ nil then goes all the way up.  Examines and sets property
         ;; Set props at this brace and all the way up
         (javaimp--parse-scopes nil)))))
 
+(defun javaimp--parse-clean-all-scopes ()
+  (remove-text-properties (point-min) (point-max)
+                          '(javaimp-parse-scope nil)))
 
-
-;; Main
-
-(defun javaimp--parse-get-package ()
-  (goto-char (point-max))
-  (when (javaimp--parse-rsb-keyword
-         "^\\s-*package\\s-+\\([^;\n]+\\)\\s-*;" nil t 1)
-    (match-string 1)))
 
 (defun javaimp--parse-get-file-classes ()
   (goto-char (point-max))
   (let (match res)
     (while (setq match (text-property-search-backward
                         'javaimp-parse-scope nil nil))
-      (when (javaimp--parse-is-class (prop-match-value match))
+      (when (javaimp--parse-is-classlike (prop-match-value match))
         (push (mapconcat #'javaimp-scope-name
                          (javaimp--parse-scopes nil)
                          ".")
               res)))))
 
-;; Imenu support
+(defun javaimp--parse-get-all-scopes()
+  (goto-char (point-max))
+  (let (res)
+    (while (setq match (text-property-search-backward
+                        'javaimp-parse-scope nil nil))
+      (push (prop-match-value match) res))
+    res))
 
-(defun javaimp-imenu-create-index ()
+(defun javaimp--parse-get-forest-for-imenu ()
   (goto-char (point-max))
-  (let (match methods top-classes)
+  (let (match methods classes top-classes)
     (while (setq match (text-property-search-backward
                         'javaimp-parse-scope nil nil))
       (let* ((scope (prop-match-value match))
-             (parent (javaimp--parse-scopes 1)))
-        (cond ((and (eq (javaimp-scope-type scope) 'method)
-                    (and parent (javaimp--parse-is-class parent)))
-               ;; TODO store parent location in scope?; reuse
-               ;; javaimp--build-tree; collect top-level classes
-               )
-               ;; TODO javaimp-imenu-group-methods - t / nil / qualified
-
-              ;; create sub-alist for each enclosing scope, which must be
-              ;; a class
-              ;;
-              ;; (INDEX-NAME . INDEX-POSITION)
-              ;; (MENU-TITLE . SUB-ALIST)
-
-              ;; TODO imenu function - to javaimp-scope-start, and 
back-to-indentation
-              )))))
+             (parent (javaimp-scope-parent scope)))
+        (cond (;; all methods
+               (and (eq (javaimp-scope-type scope) 'method)
+                    (and parent (javaimp--parse-is-classlike parent)))
+               (push scope methods))
+              (;; all classes
+               (javaimp--parse-is-classlike scope)
+               (push scope classes)
+               (when (not (javaimp-scope-parent scope))
+                 (push scope top-classes))))))
+    (mapcar
+     (lambda (class)
+       (message "Building tree for top-level class: %s"
+                (javaimp-scope-name class))
+       (javaimp--build-tree class (concat methods classes)
+                            (lambda (el tested)
+                              (equal el (javaimp-scope-parent tested)))))
+     top-classes)))
 
 (provide 'javaimp-parse)
diff --git a/javaimp-util.el b/javaimp-util.el
index 1544cc4..5e63c01 100644
--- a/javaimp-util.el
+++ b/javaimp-util.el
@@ -140,19 +140,16 @@ buffer and returns its result"
 
 ;; Tree building & search
 
-(defun javaimp--build-tree (this parent-node all)
-  (message "Building tree for module: %s" (javaimp-print-id (javaimp-module-id 
this)))
-  (let ((children
-        ;; more or less reliable way to find children is to look for
-        ;; modules with "this" as the parent
-        (seq-filter (lambda (m)
-                      (equal (javaimp-module-parent-id m) (javaimp-module-id 
this)))
-                    all)))
+(defun javaimp--build-tree (this all child-p &optional parent-node)
+  "Recursively builds tree for element THIS and its children.
+Children are those elements from ALL for which CHILD-P invoked
+with this element and tested element returns non-nil.
+PARENT-NODE is indented for recursive calls."
+  (let ((children (seq-filter (apply-partially child-p this) all)))
     (let* ((this-node (make-javaimp-node
                       :parent parent-node
                       :children nil
                       :contents this))
-          ;; recursively build child nodes
           (child-nodes
            (mapcar (lambda (child)
                      (javaimp--build-tree child this-node all))
@@ -160,35 +157,57 @@ buffer and returns its result"
       (setf (javaimp-node-children this-node) child-nodes)
       this-node)))
 
-(defun javaimp--find-node (predicate forest)
+(defun javaimp--find-node (predicate forest &optional unwrap)
   (catch 'found
     (dolist (tree forest)
-      (javaimp--find-node-in-tree-1 tree predicate))))
+      (javaimp--find-node-in-tree-1 tree predicate unwrap))))
 
-(defun javaimp--find-node-in-tree-1 (tree predicate)
+(defun javaimp--find-node-in-tree-1 (tree predicate unwrap)
   (when tree
     (if (funcall predicate (javaimp-node-contents tree))
-       (throw 'found tree))
+       (throw 'found
+               (if unwrap
+                   (javaimp-node-contents tree)
+                 tree)))
     (dolist (child (javaimp-node-children tree))
-      (javaimp--find-node-in-tree-1 child predicate))))
+      (javaimp--find-node-in-tree-1 child predicate unwrap))))
 
 
-(defun javaimp--collect-nodes (predicate forest)
+(defun javaimp--collect-nodes (predicate forest &optional unwrap)
   (apply #'seq-concatenate 'list
         (mapcar (lambda (tree)
-                  (javaimp--collect-nodes-from-tree tree predicate))
+                  (javaimp--collect-nodes-from-tree tree predicate unwrap))
                 forest)))
 
-(defun javaimp--collect-nodes-from-tree (tree &optional predicate)
+(defun javaimp--collect-nodes-from-tree (tree predicate unwrap)
   (when tree
-    (append (when (or (not predicate)
-                      (funcall predicate (javaimp-node-contents tree)))
-             (list tree))
+    (append (when (funcall predicate (javaimp-node-contents tree))
+             (list (if unwrap
+                        (javaimp-node-contents tree)
+                      tree)))
            (apply #'seq-concatenate 'list
                   (mapcar (lambda (child)
                             (javaimp--collect-nodes-from-tree child predicate))
                           (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)
+  (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 mapped)))
+          (mapcar (lambda (child)
+                    (javaimp--map-nodes-from-tree child mapper))
+                  (javaimp-node-children tree)))))
+
 (defun javaimp--get-root (node)
   (while (javaimp-node-parent node)
     (setq node (javaimp-node-parent node)))
diff --git a/javaimp.el b/javaimp.el
index eb996f3..3efdae4 100644
--- a/javaimp.el
+++ b/javaimp.el
@@ -303,13 +303,21 @@ any module file."
 ;; do not expose tree structure, return only modules
 
 (defun javaimp-find-module (predicate)
-  (let ((node (javaimp--find-node predicate javaimp-project-forest)))
-    (and node
-        (javaimp-node-contents node))))
+  "Returns first module in `javaimp-project-forest' for which
+PREDICATE returns non-nil."
+  (javaimp--find-node predicate javaimp-project-forest t))
 
 (defun javaimp-collect-modules (predicate)
-  (mapcar #'javaimp-node-contents
-         (javaimp--collect-nodes predicate javaimp-project-forest)))
+  "Returns all modules in `javaimp-project-forest' for which
+PREDICATE returns non-nil."
+  (javaimp--collect-nodes predicate javaimp-project-forest t))
+
+(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))
 
 
 ;;; Adding imports
@@ -564,6 +572,53 @@ is `ordinary' or `static'.  Interactively, NEW-IMPORTS is 
nil."
 
 
 
+;; Imenu support
+
+;;;###autoload
+(defun javaimp-imenu-create-index ()
+  (let ((forest (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))
+          ((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))
+          (t
+           ;; group methods inside their enclosing class
+           (javaimp--map-nodes
+            (lambda (scope)
+              (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-menu--make-entry scope))))
+            forest t)))))
+
+(defun javaimp-imenu--make-entry (scope)
+  (list (javaimp-scope-name scope)
+        (javaimp-scope-start scope)
+        #'javaimp-imenu--go
+        scope))
+
+(defun javaimp-imenu--go (scope)
+  (goto-char (javaimp-scope-start scope))
+  (back-to-indentation))
+
+
+
 ;; Misc
 
 (defun javaimp-reset (arg)
@@ -612,33 +667,39 @@ start (`javaimp-scope-start') instead."
                        (javaimp-scope-start scope)
                      (javaimp-scope-open-brace scope)))))))
 
-(defun javaimp-help-scopes-at-point ()
-  "Shows enclosing scopes at point in a *javaimp-scopes* buffer,
-which is first cleared."
-  (interactive)
-  (let* ((parse-sexp-ignore-comments t) ; FIXME remove with major mode
-         (parse-sexp-lookup-properties nil)
-         (scopes (save-excursion
-                   (javaimp--parse-scopes nil)))
-         (file buffer-file-name)
-         (pos (point))
-         (buf (get-buffer-create "*javaimp-scopes*")))
+
+(defun javaimp-help-show-scopes (arg)
+  "Shows scopes in a *javaimp-scopes* buffer,
+which is first cleared.  With a prefix arg, cleans all previously
+parsed scopes."
+  (interactive "P")
+  (when arg
+    (save-excursion
+      (javaimp--parse-clean-all-scopes)
+      (javaimp--parse-all-scopes)))
+  (let ((scopes (save-excursion
+                  (javaimp--parse-get-all-scopes)))
+        (file buffer-file-name)
+        (buf (get-buffer-create "*javaimp-scopes*")))
     (with-current-buffer buf
       (setq buffer-read-only nil)
       (erase-buffer)
-      (insert (propertize (format "Scopes at position %d in file:\n  %s\n\n"
-                                  pos file)
+      (insert (propertize (format "%s\n\n" file)
                           'javaimp-help-file file))
       (dolist (scope scopes)
-        (insert (propertize
-                 (concat (symbol-name (javaimp-scope-type scope))
-                         " "
-                         (javaimp-scope-name scope)
-                         "\n")
-                 'mouse-face 'highlight
-                 'help-echo "mouse-2: go to this scope"
-                 'javaimp-help-scope scope
-                 'keymap javaimp-help-keymap)))
+        (let ((depth 0)
+              (tmp scope))
+          (while (setq tmp (javaimp-scope-parent tmp))
+            (setq depth (1+ depth)))
+          (insert (propertize
+                   (format "%d: %010s %s\n"
+                           depth
+                           (symbol-name (javaimp-scope-type scope))
+                           (javaimp-scope-name scope))
+                   'mouse-face 'highlight
+                   'help-echo "mouse-2: go to this scope"
+                   'javaimp-help-scope scope
+                   'keymap javaimp-help-keymap))))
       (setq buffer-read-only t))
     (display-buffer buf)))
 



reply via email to

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