[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/javaimp df479b6: Various parsing improvements
From: |
Filipp Gunbin |
Subject: |
[elpa] externals/javaimp df479b6: Various parsing improvements |
Date: |
Tue, 8 Jun 2021 14:33:28 -0400 (EDT) |
branch: externals/javaimp
commit df479b68d342e99b91a3a362545a24f02eb9d727
Author: Filipp Gunbin <fgunbin@fastmail.fm>
Commit: Filipp Gunbin <fgunbin@fastmail.fm>
Various parsing improvements
---
javaimp-parse.el | 99 ++++++++++++++++++++++++++++----------------------------
javaimp-tests.el | 58 +++++++++++++++++++++++++++++++--
javaimp.el | 32 ++++++++++++++++--
3 files changed, 135 insertions(+), 54 deletions(-)
diff --git a/javaimp-parse.el b/javaimp-parse.el
index 2a17d3b..89f5e0d 100644
--- a/javaimp-parse.el
+++ b/javaimp-parse.el
@@ -33,7 +33,7 @@ present."
(cl-defstruct javaimp-scope
type ; one of anonymous-class, class, interface, enum, local-class,
- ; method, statement, unknown
+ ; method, statement, simple-statement, unknown
name
start
open-brace)
@@ -45,17 +45,12 @@ present."
"static" ;static initializer block
))
-(defun javaimp--parse-block-re (keywords)
+(defconst javaimp--parse-class-re
(concat
- (regexp-opt keywords 'words)
+ (regexp-opt javaimp--parse-class-keywords 'words)
(rx (and (+ (syntax whitespace))
(group (+ (any alnum ?_)))))))
-(defconst javaimp--parse-class-re
- (javaimp--parse-block-re javaimp--parse-class-keywords))
-(defconst javaimp--parse-stmt-re
- (javaimp--parse-block-re javaimp--parse-stmt-keywords))
-
(defsubst javaimp--parse-is-class (scope)
(member (symbol-name (javaimp-scope-type scope))
javaimp--parse-class-keywords))
@@ -171,27 +166,46 @@ present."
;;; Scopes
(defvar javaimp--parse-scope-hook
- '(;; should be before method/stmt because looks similar, but with
- ;; "new " in front
+ '(javaimp--parse-scope-simple-stmt
+ ;; should be before method/stmt because looks similar, but with
+ ;; "new" in front
javaimp--parse-scope-anonymous-class
javaimp--parse-scope-method-or-stmt
javaimp--parse-scope-class
- javaimp--parse-scope-unknown ; catch-all
+ javaimp--parse-scope-unknown
))
+(defun javaimp--parse-preceding (regexp scope-start &optional skip-count)
+ (and (javaimp--rsb-outside-context regexp nil t)
+ (ignore-errors
+ ;; Does our match belong to the right block?
+ (= (scan-lists (match-end 0) (or skip-count 1) -1)
+ (1+ scope-start)))))
+
(defun javaimp--parse-scope-class (state)
+ "Attempts to parse `class' / `interface' / `enum' scope. Some of
+those may later become `local-class'."
(save-excursion
- (if (and (javaimp--rsb-outside-context javaimp--parse-class-re nil t)
- ;; Does found declaration belong to the right block?
- (= (scan-lists (match-end 0) 1 -1)
- (1+ (nth 1 state))))
+ (if (javaimp--parse-preceding javaimp--parse-class-re (nth 1 state))
(make-javaimp-scope :type (intern (match-string 1))
:name (match-string 2)
:start (match-beginning 1)
:open-brace (nth 1 state)))))
+(defun javaimp--parse-scope-simple-stmt (state)
+ "Attempts to parse `simple-statement' scope."
+ (save-excursion
+ (if (javaimp--parse-preceding (regexp-opt javaimp--parse-stmt-keywords
'words)
+ (nth 1 state))
+ (make-javaimp-scope
+ :type 'simple-statement
+ :name (match-string 1)
+ :start (point)
+ :open-brace (nth 1 state)))))
+
(defun javaimp--parse-scope-anonymous-class (state)
+ "Attempts to parse `anonymous-class' scope."
(save-excursion
;; skip arg-list and ws
(when (and (progn
@@ -202,10 +216,7 @@ present."
(scan-lists (point) -1 0))))
(skip-syntax-backward "-")
(let ((end (point)))
- (when (and (javaimp--rsb-outside-context "\\<new\\>" nil t)
- ;; Does found "new" belong to the right block?
- (= (scan-lists (match-end 0) 1 -1)
- (1+ (nth 1 state))))
+ (when (javaimp--parse-preceding "\\<new\\>" (nth 1 state) 2)
(goto-char (match-end 0))
(skip-syntax-forward "-")
(make-javaimp-scope :type 'anonymous-class
@@ -216,6 +227,7 @@ present."
:open-brace (nth 1 state)))))))
(defun javaimp--parse-scope-method-or-stmt (state)
+ "Attempts to parse `method' or `statement' scope."
(save-excursion
(let ((throws-args (javaimp--parse-scope-method-throws state)))
(when (and (not (eq throws-args t))
@@ -256,12 +268,11 @@ present."
to parse throws clause backwards, returning THROWS-ARGS in the
same format as `javaimp--parse-arglist' (but here, only TYPE
element component will be present). Point is left at the
-position from where method signature parsing may be continued.
+xXposition from where method signature parsing may be continued.
Returns t if parsing failed and should not be continued."
(let ((pos (point)))
(when (javaimp--rsb-outside-context "\\<throws\\>" nil t)
- (if (ignore-errors
- ;; Does found "throws" belong to the right block?
+ (if (ignore-errors ;As in javaimp--parse-preceding
(= (scan-lists (match-end 0) 1 -1)
(1+ (nth 1 state))))
(let ((res (save-match-data
@@ -284,8 +295,8 @@ Returns t if parsing failed and should not be continued."
(goto-char pos)
nil))))
-
(defun javaimp--parse-scope-unknown (state)
+ "Catch-all parser which produces `unknown' scope."
(make-javaimp-scope :type 'unknown
:name "unknown"
:start nil
@@ -325,36 +336,24 @@ Returns t if parsing failed and should not be continued."
;; Main
(defun javaimp--parse-get-package ()
- (let ((parse-sexp-ignore-comments t) ;TODO set in mode
- (parse-sexp-lookup-properties nil))
- (save-excursion
- (save-restriction
- (widen)
- (goto-char (point-max))
- (when (javaimp--rsb-outside-context
- "^\\s *package\\s +\\([^;]+\\)\\s *;" nil t 1)
- (match-string 1))))))
-
-(defun javaimp--parse-get-file-classes (file)
- (with-temp-buffer
- (insert-file-contents file)
- (goto-char (point-max))
- (let ((package (javaimp--parse-get-package))
- (parse-sexp-ignore-comments t) ;TODO set in mode
- (parse-sexp-lookup-properties nil)
- res)
- (while (javaimp--rsb-outside-context javaimp--parse-class-re nil t)
- (save-excursion
+ (goto-char (point-max))
+ (when (javaimp--rsb-outside-context
+ "^\\s-*package\\s-+\\([^;\n]+\\)\\s-*;" nil t 1)
+ (match-string 1)))
+
+(defun javaimp--parse-get-file-classes ()
+ (goto-char (point-max))
+ (let (res)
+ (while (javaimp--rsb-outside-context javaimp--parse-class-re nil t)
+ (save-excursion
+ (let ((parse-sexp-ignore-comments t) ; FIXME remove with major mode
+ (parse-sexp-lookup-properties nil))
(when (and (ignore-errors
(goto-char (scan-lists (point) 1 -1)))
(= (char-before) ?{))
- (let ((scopes (javaimp--parse-scopes nil))
- curr)
+ (let ((scopes (javaimp--parse-scopes nil)))
(when (seq-every-p #'javaimp--parse-is-class scopes)
- (setq curr (mapconcat #'javaimp-scope-name scopes "."))
- (if package
- (setq curr (concat package "." curr)))
- (push curr res))))))
- res)))
+ (push (mapconcat #'javaimp-scope-name scopes ".") res)))))))
+ res))
(provide 'javaimp-parse)
diff --git a/javaimp-tests.el b/javaimp-tests.el
index b475fa1..fef7210 100644
--- a/javaimp-tests.el
+++ b/javaimp-tests.el
@@ -23,6 +23,56 @@
;; (should (eql (length projects) 2)))))
+(defun javaimp-test--check-scope (parse-hook test-data)
+ (declare (indent 1))
+ (dolist (data test-data)
+ (with-temp-buffer
+ (insert (nth 0 data))
+ (java-mode)
+ (let* ((parse-sexp-ignore-comments t) ;FIXME remove with major mode
+ (parse-sexp-lookup-properties nil)
+ (javaimp--parse-scope-hook parse-hook)
+ (scope (car (javaimp--parse-scopes 1))))
+ (should-not (null scope))
+ (should (eq (javaimp-scope-type scope) (nth 1 data)))
+ (should (equal (javaimp-scope-name scope) (nth 2 data)))))))
+
+(ert-deftest javaimp-test--parse-scope-class ()
+ (javaimp-test--check-scope #'javaimp--parse-scope-class
+ '(("public class Foo<Bar, Baz> {"
+ class "Foo")
+ ("interface Foo<Bar, Baz> {"
+ interface "Foo")
+ ("private enum Foo {"
+ enum "Foo"))))
+
+(ert-deftest javaimp-test--parse-scope-anonymous-class ()
+ (javaimp-test--check-scope #'javaimp--parse-scope-anonymous-class
+ '((" = new Object<Class1, Class2>(1 + 1, baz) {"
+ anonymous-class "Anon_Object<Class1, Class2>")
+ (" = (obj.getField()).new Object<Class1, Class2>(1, baz) {"
+ anonymous-class "Anon_Object<Class1, Class2>")
+ (" = obj.new Object<>(1, baz) {"
+ anonymous-class "Anon_Object<>"))))
+
+(ert-deftest javaimp-test--parse-scope-method-or-stmt ()
+ (javaimp-test--check-scope #'javaimp--parse-scope-method-or-stmt
+ '(("static void foo_bar(String a, int b) {"
+ method "foo_bar(String a, int b)")
+ ("void foo_bar(String a, int b) throws E1, E2 {"
+ method "foo_bar(String a, int b) throws E1, E2")
+ ("if (foo_bar(a, b) < 2) {"
+ statement "if"))))
+
+(ert-deftest javaimp-test--parse-scope-simple-stmt ()
+ (javaimp-test--check-scope #'javaimp--parse-scope-simple-stmt
+ '(("try {"
+ simple-statement "try")
+ ;; static initializer also falls in this category
+ ("static {"
+ simple-statement "static"))))
+
+
(ert-deftest javaimp-test--parse-arglist ()
(dolist (data '(("")
(" ")
@@ -69,6 +119,7 @@ Exception4<? super Exception5>>")
(should (equal (javaimp--parse-arglist (point-min) (point-max) t)
(cdr data))))))
+
(ert-deftest javaimp-test--parse-get-package ()
(with-temp-buffer
(insert "//package org.commented1;
@@ -76,8 +127,9 @@ Exception4<? super Exception5>>")
package org.foo;")
(should (equal (javaimp--parse-get-package) "org.foo"))))
-(ert-deftest javaimp-test--parse-get-file-classes ()
- (should (equal (javaimp--parse-get-file-classes
+
+(ert-deftest javaimp-test--get-file-classes ()
+ (should (equal (javaimp--get-file-classes
(concat javaimp--basedir
"testdata/test-get-file-classes-1.java"))
'("org.foo.Top"
"org.foo.Top.CInner1"
@@ -87,3 +139,5 @@ Exception4<? super Exception5>>")
"org.foo.Top.IInner1.IInner1_CInner1"
"org.foo.Top.EInner1"
"org.foo.Top.EInner1.EInner1_EInner1"))))
+
+(provide 'javaimp-tests)
diff --git a/javaimp.el b/javaimp.el
index 767bab8..7d88bb5 100644
--- a/javaimp.el
+++ b/javaimp.el
@@ -412,7 +412,10 @@ prefix arg is given, don't do this filtering."
javaimp-additional-source-dirs)))
(defun javaimp--dir-above-current-package ()
- (let ((package (javaimp--parse-get-package)))
+ (let ((package (save-excursion
+ (save-restriction
+ (widen)
+ (javaimp--parse-get-package)))))
(when package
(string-remove-suffix
(mapconcat #'file-name-as-directory
@@ -421,11 +424,20 @@ prefix arg is given, don't do this filtering."
(defun javaimp--get-directory-classes (dir)
(if (file-accessible-directory-p dir)
- (seq-mapcat #'javaimp--parse-get-file-classes
+ (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)
+ (with-temp-buffer
+ (insert-file-contents file)
+ (let ((package (javaimp--parse-get-package)))
+ (mapcar (lambda (class)
+ (if package
+ (concat package "." class)))
+ (javaimp--parse-get-file-classes)))))
+
;; Organizing imports
@@ -543,6 +555,9 @@ is `ordinary' or `static'. Interactively, NEW-IMPORTS is
nil."
(setq last-order order)))))
+
+;; Misc
+
(defun javaimp-reset (arg)
"Forget loaded trees state. With prefix arg, also reset jars
cache."
@@ -552,6 +567,19 @@ cache."
(when arg
(setq javaimp-cached-jars nil)))
+(defun javaimp-show-scopes-at-point ()
+ "Shows current scopes in a *javaimp-parse* buffer. Useful for
+debugging."
+ (interactive)
+ (with-output-to-temp-buffer "*javaimp-parse*"
+ (let ((parse-sexp-ignore-comments t) ; FIXME remove with major mode
+ (parse-sexp-lookup-properties nil))
+ (prin1 (javaimp--parse-scopes nil)))
+ (with-current-buffer standard-output
+ (fundamental-mode)
+ (goto-char (point-min))
+ (indent-pp-sexp t))))
+
(provide 'javaimp)
;;; javaimp.el ends here
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [elpa] externals/javaimp df479b6: Various parsing improvements,
Filipp Gunbin <=