[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)))
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [elpa] scratch/javaimp-wip 551b1a3: wip,
Filipp Gunbin <=