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

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

[elpa] externals/javaimp 09c93e4: * javaimp-parse.el: Improve handling o


From: Filipp Gunbin
Subject: [elpa] externals/javaimp 09c93e4: * javaimp-parse.el: Improve handling of ws / comments
Date: Thu, 10 Jun 2021 16:31:58 -0400 (EDT)

branch: externals/javaimp
commit 09c93e43a246b04a9737f2aea558aeaa67dc8974
Author: Filipp Gunbin <fgunbin@fastmail.fm>
Commit: Filipp Gunbin <fgunbin@fastmail.fm>

    * javaimp-parse.el: Improve handling of ws / comments
---
 javaimp-parse.el | 202 +++++++++++++++++++++++++++++++------------------------
 javaimp-tests.el |  88 +++++++++++++++---------
 2 files changed, 172 insertions(+), 118 deletions(-)

diff --git a/javaimp-parse.el b/javaimp-parse.el
index 89f5e0d..df5df2a 100644
--- a/javaimp-parse.el
+++ b/javaimp-parse.el
@@ -45,12 +45,6 @@ present."
     "static"                            ;static initializer block
     ))
 
-(defconst javaimp--parse-class-re
-  (concat
-   (regexp-opt javaimp--parse-class-keywords 'words)
-   (rx (and (+ (syntax whitespace))
-            (group (+ (any alnum ?_)))))))
-
 (defsubst javaimp--parse-is-class (scope)
   (member (symbol-name (javaimp-scope-type scope)) 
javaimp--parse-class-keywords))
 
@@ -74,67 +68,89 @@ present."
         (goto-char (point-max))
         (ignore-errors
           (let (res)
-            (while (not (bobp))
+            (while (progn
+                     (javaimp--parse-skip-back-until)
+                     (not (bobp)))
               (push (javaimp--parse-arglist-one-arg only-type) res)
               ;; move back to the previous argument, if any
-              (when (javaimp--parse-arglist-until (lambda ()
-                                                    (and (not (bobp))
-                                                         (= (char-before) 
?,))))
-                (backward-char)))
+              (when (javaimp--parse-skip-back-until (lambda (last-what 
last-pos)
+                                                      (and (not (bobp))
+                                                           (= (char-before) 
?,))))
+                (backward-char)))       ; skip comma
             res))))))
 
 (defun javaimp--parse-arglist-one-arg (only-type)
-  ;; Parse one argument as type and name backwards starting from point
-  ;; and return it in the form (TYPE . NAME).  Name is skipped if
-  ;; ONLY-TYPE is non-nil.  Leave point at where the job is done:
-  ;; skipping further backwards is done by the caller.
+  "Parse one argument as type and name backwards starting from
+point and return it in the form (TYPE . NAME).  Name is skipped
+if ONLY-TYPE is non-nil.  Leave point at where the job is done:
+skipping further backwards is done by the caller."
   (let ((limit (progn
-                 (skip-syntax-backward "-")
+                 (javaimp--parse-skip-back-until)
                  (point)))
         name)
     ;; Parse name
     (unless only-type
       (if (= 0 (skip-syntax-backward "w_"))
-          (error "Cannot parse argument name"))
-      (setq name (buffer-substring-no-properties (point) limit))
-      (skip-syntax-backward "-")
-      (setq limit (point)))
+          (error "Cannot parse argument name")
+        (setq name (buffer-substring-no-properties (point) limit))
+        (javaimp--parse-skip-back-until)
+        (setq limit (point))))
     ;; Parse type: allow anything, but stop at the word boundary which
     ;; is not inside list (this is presumably the type start..)
-    (if (javaimp--parse-arglist-until (lambda ()
-                                        (save-excursion
-                                          (skip-syntax-forward "-" limit)
-                                          (looking-at "\\_<"))))
+    (if-let ((last-skip
+              (javaimp--parse-skip-back-until (lambda (last-what last-pos)
+                                                (save-excursion
+                                                  (if last-pos (goto-char 
last-pos))
+                                                  (looking-at "\\_<"))))))
         (progn
-          (skip-syntax-forward "-")     ;undo skipping by ..-until
+          (unless (eq last-skip t)
+            (goto-char (cdr last-skip))) ;undo skipping by ..-until
           (let ((type (replace-regexp-in-string
                        "[[:space:]\n]+" " "
                        (buffer-substring-no-properties (point) limit))))
             (cons type name)))
       (error "Cannot parse argument type"))))
 
-(defun javaimp--parse-arglist-until (stop-p)
-  ;; Goes backwards until position at which STOP-P returns non-nil.
-  ;; Returns non-nil if stopped on this condition, nil if reached bob.
-  ;; STOP-P is invoked (possibly at the bob) without arguments and
-  ;; should not move point.  Backward movement also skips any
-  ;; whitespace, so STOP-P looking forward should be prepared to
-  ;; see leading whitespace.
+(defun javaimp--parse-skip-back-until (&optional stop-p)
+  "Goes backwards until position at which STOP-P returns non-nil, or reaching 
bob.
+
+STOP-P is invoked with two arguments which describe the last
+non-ws thing skipped: LAST-WHAT (symbol - either 'list' or
+'char') and LAST-POS.  If STOP-P returns non-nil, then the return
+value is also non-nil: either (LAST-WHAT . LAST-POS) if both are
+non-nil or t.  Otherwise the return value is nil.
+
+If STOP-P wants to look forward, it should be prepared to see
+whitespace / comments, this is because backward movement skips
+them before invoking STOP-P.  It should not move point.  If
+omitted, it defaults to `always'."
+  (or stop-p (setq stop-p #'always))
   (catch 'done
-    (while t
-      (skip-syntax-backward "-")
-      (let ((state (syntax-ppss)))
-        (cond ((syntax-ppss-context state)
-               ;; move out of comment/string if in one
-               (goto-char (nth 8 state)))
-              ((funcall stop-p)
-               (throw 'done t))
-              ((bobp)
-               (throw 'done nil))
-              ((= (char-syntax (char-before)) ?\))
-               (backward-list))
-              (t
-               (backward-char)))))))
+    (let (last-what last-pos)
+      (while t
+        (skip-syntax-backward " ")
+        (let ((state (syntax-ppss)))
+          (cond ((syntax-ppss-context state)
+                 ;; move out of comment/string if in one
+                 (goto-char (nth 8 state)))
+                ((and (not (bobp))
+                      ;; FIXME use syntax-after instead
+                      (member (char-syntax (char-before)) '(?> ?!)))
+                 (backward-char))
+                ((funcall stop-p last-what last-pos)
+                 (throw 'done (if (and last-what last-pos)
+                                  (cons last-what last-pos)
+                                t)))
+                ((bobp)
+                 (throw 'done nil))
+                ((= (char-syntax (char-before)) ?\))
+                 (backward-list)
+                 (setq last-what 'list
+                       last-pos (point)))
+                (t
+                 (backward-char)
+                 (setq last-what 'char
+                       last-pos (point)))))))))
 
 
 
@@ -166,12 +182,12 @@ present."
 ;;; Scopes
 
 (defvar javaimp--parse-scope-hook
-  '(javaimp--parse-scope-simple-stmt
-    ;; should be before method/stmt because looks similar, but with
+  '(;; 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-simple-stmt
+    javaimp--parse-scope-method-or-stmt
     javaimp--parse-scope-unknown
     ))
 
@@ -184,14 +200,31 @@ present."
             (1+ scope-start)))))
 
 (defun javaimp--parse-scope-class (state)
-  "Attempts to parse `class' / `interface' / `enum' scope.  Some of
-those may later become `local-class'."
+  "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 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)))))
+    (if (javaimp--parse-preceding (regexp-opt javaimp--parse-class-keywords 
'words)
+                                  (nth 1 state))
+        (let* ((keyword-start (match-beginning 1))
+               (keyword-end (match-end 1))
+               (decl-suffix (progn
+                              (goto-char (nth 1 state))
+                              (or (javaimp--parse-decl-suffix "\\<extends\\>"
+                                                              state 
keyword-end)
+                                  (javaimp--parse-decl-suffix 
"\\<implements\\>"
+                                                              state 
keyword-end))))
+               arglist)
+          (unless (eq decl-suffix t)
+            ;; we either skipped back over the valid declaration
+            ;; suffix(-es), or there isn't any
+            (setq arglist (javaimp--parse-arglist keyword-end (point) t))
+            (when (= (length arglist) 1)
+              (make-javaimp-scope :type (intern
+                                         (buffer-substring-no-properties
+                                          keyword-start keyword-end))
+                                  :name (caar arglist)
+                                  :start keyword-start
+                                  :open-brace (nth 1 state))))))))
 
 (defun javaimp--parse-scope-simple-stmt (state)
   "Attempts to parse `simple-statement' scope."
@@ -209,30 +242,29 @@ those may later become `local-class'."
   (save-excursion
     ;; skip arg-list and ws
     (when (and (progn
-                 (skip-syntax-backward "-")
+                 (javaimp--parse-skip-back-until)
                  (= (char-before) ?\)))
                (ignore-errors
                  (goto-char
                   (scan-lists (point) -1 0))))
-      (skip-syntax-backward "-")
-      (let ((end (point)))
+      (let ((end (point))
+            start arglist)
         (when (javaimp--parse-preceding "\\<new\\>" (nth 1 state) 2)
-          (goto-char (match-end 0))
-          (skip-syntax-forward "-")
-          (make-javaimp-scope :type 'anonymous-class
-                              :name (concat "Anon_"
-                                            (buffer-substring-no-properties
-                                             (point) end))
-                              :start (match-beginning 0)
-                              :open-brace (nth 1 state)))))))
+          (setq start (match-beginning 0)
+                arglist (javaimp--parse-arglist (match-end 0) end t))
+          (when (= (length arglist) 1)
+            (make-javaimp-scope :type 'anonymous-class
+                                :name (caar arglist)
+                                :start start
+                                :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)))
+    (let ((throws-args (javaimp--parse-decl-suffix "\\<throws\\>" state)))
       (when (and (not (eq throws-args t))
                  (progn
-                   (skip-syntax-backward "-")
+                   (javaimp--parse-skip-back-until)
                    (= (char-before) ?\)))
                  (ignore-errors
                    (goto-char
@@ -241,7 +273,7 @@ those may later become `local-class'."
                (arglist-region (cons (1+ (point))
                                      (1- (scan-lists (point) 1 0))))
                (count (progn
-                        (skip-syntax-backward "-")
+                        (javaimp--parse-skip-back-until)
                         (skip-syntax-backward "w_")))
                (name (and (< count 0)
                           (buffer-substring-no-properties
@@ -263,28 +295,21 @@ those may later become `local-class'."
              :start (point)
              :open-brace (nth 1 state))))))))
 
-(defun javaimp--parse-scope-method-throws (state)
-  "Subroutine of `javaimp--parse-scope-method-or-stmt'.  Attempts
-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
-xXposition from where method signature parsing may be continued.
-Returns t if parsing failed and should not be continued."
+(defun javaimp--parse-decl-suffix (regexp state &optional bound)
+  "Subroutine of other scope parsers.  Attempts to parse
+declaration suffix backwards (but not farther than BOUND),
+returning 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 scope
+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)
+    (when (javaimp--rsb-outside-context regexp bound t)
       (if (ignore-errors             ;As in javaimp--parse-preceding
             (= (scan-lists (match-end 0) 1 -1)
                (1+ (nth 1 state))))
           (let ((res (save-match-data
-                       (javaimp--parse-arglist (save-excursion
-                                                 (goto-char (match-end 0))
-                                                 (skip-syntax-forward "-")
-                                                 (point))
-                                               (save-excursion
-                                                 (goto-char pos)
-                                                 (skip-syntax-backward "-")
-                                                 (point))
-                                               t))))
+                       (javaimp--parse-arglist (match-end 0) pos t))))
             (if res
                 (goto-char (match-beginning 0))
               ;; Something's wrong here: tell the caller to stop
@@ -344,7 +369,8 @@ Returns t if parsing failed and should not be continued."
 (defun javaimp--parse-get-file-classes ()
   (goto-char (point-max))
   (let (res)
-    (while (javaimp--rsb-outside-context javaimp--parse-class-re nil t)
+    (while (javaimp--rsb-outside-context
+            (regexp-opt javaimp--parse-class-keywords 'words) nil t)
       (save-excursion
         (let ((parse-sexp-ignore-comments t) ; FIXME remove with major mode
               (parse-sexp-lookup-properties nil))
diff --git a/javaimp-tests.el b/javaimp-tests.el
index fef7210..80d72c4 100644
--- a/javaimp-tests.el
+++ b/javaimp-tests.el
@@ -23,54 +23,76 @@
 ;;       (should (eql (length projects) 2)))))
 
 
-(defun javaimp-test--check-scope (parse-hook test-data)
+(defun javaimp-test--check-scope (parse-hook &rest test-items)
   (declare (indent 1))
-  (dolist (data test-data)
+  (dolist (item test-items)
     (with-temp-buffer
-      (insert (nth 0 data))
+      (insert (nth 0 item))
       (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)))))))
+        (should (eq (javaimp-scope-type scope) (nth 1 item)))
+        (should (equal (javaimp-scope-name scope) (nth 2 item)))))))
 
 (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"))))
+    '("class Foo {"
+      class "Foo")
+    '("class Foo extends Bar {"
+      class "Foo")
+    '("class Foo implements Bar {"
+      class "Foo")
+    '("class Foo implements Bar, Baz {"
+      class "Foo")
+    '("class Foo extends Bar implements Baz1, Baz2 {"
+      class "Foo")
+    '("public\nclass\nFoo\nextends\nBar\nimplements\nBaz1\n,\nBaz2\n{"
+      class "Foo")
+    '("class Foo<Bar, Baz> extends FooSuper<Bar, Baz> \
+implements Interface1<Bar, Baz>, Interface2 {"
+      class "Foo<Bar, Baz>")
+    '("interface Foo<Bar, Baz> {"
+      interface "Foo<Bar, Baz>")
+    '("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<>"))))
+    '(" = new Object<Class1, Class2>(1 + 1, baz) {"
+      anonymous-class "Object<Class1, Class2>")
+    '(" =\nnew\nObject\n<\nClass1\n,\nClass2\n>\n(\n1\n+\n1\n,\nbaz\n)\n{"
+      anonymous-class "Object < Class1 , Class2 >")
+    '(" = (obj.getField()).new Object<Class1, Class2>(1, baz) {"
+      anonymous-class "Object<Class1, Class2>")
+    '(" = obj.new Object<>(1, baz) {"
+      anonymous-class "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"))))
+    '("static void foo_bar(String a, int b) {"
+      method "foo_bar(String a, int b)")
+    '("static void\nfoo_bar\n(\nString\na\n,\nint\nb\n)\n{"
+      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")
+    '("void foo_bar()
+throws E1 {"
+      method "foo_bar() throws E1")
+    '("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"))))
+    '("try {"
+      simple-statement "try")
+    '("\ntry\n{"
+      simple-statement "try")
+    ;; static initializer also falls in this category
+    '("static {"
+      simple-statement "static")))
 
 
 (ert-deftest javaimp-test--parse-arglist ()
@@ -78,6 +100,9 @@
                   ("  ")
                   ("int i"
                    ("int" . "i"))
+                  ("\nint\ni\n,\nint\nj\n"
+                   ("int" . "i")
+                   ("int" . "j"))
                   (" List<? extends Comparable<? super T>> list, T... elements"
                    ("List<? extends Comparable<? super T>>" . "list")
                    ("T..." . "elements"))
@@ -104,6 +129,9 @@
                   ("  ")
                   ("Exception1"
                    ("Exception1"))
+                  ("\nEx1\n,\nEx2\n"
+                   ("Ex1")
+                   ("Ex2"))
                   (" Exception1 , org.foo_bar_3.Exception_2 "
                    ("Exception1")
                    ("org.foo_bar_3.Exception_2"))
@@ -132,8 +160,8 @@ Exception4<? super Exception5>>")
   (should (equal (javaimp--get-file-classes
                   (concat javaimp--basedir 
"testdata/test-get-file-classes-1.java"))
                  '("org.foo.Top"
-                   "org.foo.Top.CInner1"
-                   "org.foo.Top.CInner1.CInner1_CInner1"
+                   "org.foo.Top.CInner1<T, S>"
+                   "org.foo.Top.CInner1<T, S>.CInner1_CInner1"
                    "org.foo.Top.IInner1"
                    "org.foo.Top.IInner1.IInner1_IInner1"
                    "org.foo.Top.IInner1.IInner1_CInner1"



reply via email to

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