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

[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



reply via email to

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